talon-agent 5.1.0 → 5.2.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 (99) hide show
  1. package/README.md +3 -1
  2. package/bin/talon.js +35 -0
  3. package/package.json +2 -2
  4. package/prompts/identity.md +10 -2
  5. package/prompts/system/agent-brief.md +43 -0
  6. package/src/app.ts +19 -26
  7. package/src/backend/builtins.ts +26 -7
  8. package/src/backend/claude-sdk/one-shot.ts +13 -5
  9. package/src/backend/remote-server/index.ts +6 -4
  10. package/src/backend/remote-server/model-catalog/index.ts +4 -10
  11. package/src/backend/remote-server/model-catalog/provider.ts +3 -3
  12. package/src/backend/remote-server/profiles/bind.ts +225 -0
  13. package/src/backend/remote-server/profiles/index.ts +10 -0
  14. package/src/backend/remote-server/profiles/kilo.ts +82 -0
  15. package/src/backend/remote-server/profiles/opencode.ts +61 -0
  16. package/src/backend/remote-server/server-bindings.ts +3 -4
  17. package/src/bootstrap.ts +15 -1
  18. package/src/cli/chat.ts +5 -0
  19. package/src/cli/events.ts +9 -0
  20. package/src/core/agents/context.ts +48 -0
  21. package/src/core/agents/delivery.ts +167 -0
  22. package/src/core/agents/index.ts +37 -0
  23. package/src/core/agents/prompt.ts +116 -0
  24. package/src/core/agents/registry.ts +426 -0
  25. package/src/core/agents/runner.ts +448 -0
  26. package/src/core/agents/types.ts +124 -0
  27. package/src/core/background/cron/job-oneshot.ts +7 -12
  28. package/src/core/background/cron/job-prompt.ts +1 -1
  29. package/src/core/background/{cron/isolated-agent.ts → isolated-agent.ts} +45 -24
  30. package/src/core/background/run-log.ts +33 -0
  31. package/src/core/bus/events.ts +49 -2
  32. package/src/core/config/index.ts +25 -0
  33. package/src/core/engine/gateway-actions/agents/control.ts +299 -0
  34. package/src/core/engine/gateway-actions/agents/index.ts +31 -0
  35. package/src/core/engine/gateway-actions/agents/report.ts +107 -0
  36. package/src/core/engine/gateway-actions/index.ts +30 -0
  37. package/src/core/engine/gateway-actions/native/exec-remote.ts +1 -1
  38. package/src/core/engine/gateway-actions/native/exec.ts +1 -1
  39. package/src/core/engine/gateway-actions/native/read.ts +1 -1
  40. package/src/core/engine/gateway-actions/native/search.ts +1 -1
  41. package/src/core/engine/gateway-actions/native/teleport.ts +1 -1
  42. package/src/core/engine/gateway-actions/native/write.ts +1 -1
  43. package/src/core/engine/gateway-routes.ts +12 -0
  44. package/src/core/engine/gateway.ts +96 -25
  45. package/src/core/frontend-runtime/capabilities.ts +18 -0
  46. package/src/core/frontend-runtime/index.ts +4 -0
  47. package/src/core/frontend-runtime/lifecycle.ts +33 -0
  48. package/src/core/frontend-runtime/registry.ts +3 -3
  49. package/src/core/frontend-runtime/run-loop.ts +59 -0
  50. package/src/core/mesh/{registry.ts → devices/registry.ts} +4 -4
  51. package/src/core/mesh/{service.ts → devices/service.ts} +13 -10
  52. package/src/core/mesh/{teleport.ts → devices/teleport.ts} +2 -2
  53. package/src/core/mesh/index.ts +6 -2
  54. package/src/core/mesh/{bridge-links.ts → links/bridge-links.ts} +1 -1
  55. package/src/core/mesh/{companion-pairing.ts → links/companion-pairing.ts} +1 -1
  56. package/src/core/mesh/{node-binaries.ts → links/node-binaries.ts} +5 -5
  57. package/src/core/mesh/{node-provision.ts → links/node-provision.ts} +1 -1
  58. package/src/core/mesh/{common.ts → tool-surface.ts} +7 -2
  59. package/src/core/mesh/{device-files.ts → transfers/device-files.ts} +5 -5
  60. package/src/core/prompt/embedded-prompts.ts +38 -36
  61. package/src/core/tasks/types.ts +2 -2
  62. package/src/core/tools/index.ts +5 -0
  63. package/src/core/tools/ops/agents.ts +195 -0
  64. package/src/core/tools/ops/bridge.ts +4 -0
  65. package/src/core/tools/types.ts +1 -0
  66. package/src/core/types.ts +1 -1
  67. package/src/frontend/discord/commands/info.ts +1 -1
  68. package/src/frontend/discord/render.ts +1 -1
  69. package/src/frontend/native/bridge/routes/mesh.ts +1 -1
  70. package/src/frontend/native/index.ts +2 -0
  71. package/src/frontend/presentation/reports.ts +1 -1
  72. package/src/frontend/teams/index.ts +4 -3
  73. package/src/frontend/telegram/commands/info.ts +61 -20
  74. package/src/frontend/telegram/index.ts +27 -4
  75. package/src/frontend/telegram/render/reports.ts +1 -1
  76. package/src/frontend/terminal/index.ts +6 -2
  77. package/src/frontend/whatsapp/connection/connection.ts +62 -11
  78. package/src/frontend/whatsapp/index.ts +25 -1
  79. package/src/frontend/whatsapp/runtime.ts +7 -0
  80. package/src/util/log.ts +1 -0
  81. package/src/backend/kilo/factory.ts +0 -53
  82. package/src/backend/kilo/handler/index.ts +0 -2
  83. package/src/backend/kilo/handler/message.ts +0 -44
  84. package/src/backend/kilo/index.ts +0 -61
  85. package/src/backend/kilo/model-provider.ts +0 -36
  86. package/src/backend/kilo/models/index.ts +0 -55
  87. package/src/backend/kilo/one-shot.ts +0 -42
  88. package/src/backend/kilo/server.ts +0 -98
  89. package/src/backend/kilo/sessions.ts +0 -37
  90. package/src/backend/opencode/factory.ts +0 -53
  91. package/src/backend/opencode/handler/index.ts +0 -2
  92. package/src/backend/opencode/handler/message.ts +0 -44
  93. package/src/backend/opencode/index.ts +0 -42
  94. package/src/backend/opencode/model-provider.ts +0 -36
  95. package/src/backend/opencode/models/index.ts +0 -54
  96. package/src/backend/opencode/one-shot.ts +0 -42
  97. package/src/backend/opencode/server.ts +0 -80
  98. package/src/backend/opencode/sessions.ts +0 -35
  99. /package/src/core/mesh/{transfers.ts → transfers/transfers.ts} +0 -0
@@ -1,55 +0,0 @@
1
- /**
2
- * Kilo model catalog — binder over the shared remote-server model-catalog
3
- * module (see `backend/remote-server/model-catalog/`).
4
- *
5
- * Kilo's provider-bucket API is forked from OpenCode's, so the catalog,
6
- * resolution, and presentation logic is the shared implementation; this file
7
- * only binds the Kilo SDK client + presentation knobs and re-exports the
8
- * result under the historical `OpenCode*`-prefixed names (retained on
9
- * purpose — the names match the wire shape the upstream actually emits).
10
- *
11
- * Knobs: Kilo's model picker renders through Discord StringSelectMenus,
12
- * which allow 25 options and values up to 100 chars with any characters —
13
- * Kilo ids routinely contain "/" and ":" (e.g. "inclusionai/ling-2.6-1t:free").
14
- */
15
-
16
- import { ensureServer, onServerStop } from "../server.js";
17
- import { createRemoteModelCatalogModule } from "../../remote-server/model-catalog/index.js";
18
-
19
- export type {
20
- RemoteModelCatalogEntry as OpenCodeModelCatalogEntry,
21
- RemoteModelCatalog as OpenCodeModelCatalog,
22
- RemoteModelResolution as OpenCodeModelResolution,
23
- ModelButton,
24
- } from "../../remote-server/model-catalog/index.js";
25
- export {
26
- sortCatalogModels,
27
- getRemoteModelSelectionValue as getOpenCodeModelSelectionValue,
28
- resolveRemoteModelInput as resolveOpenCodeModelInput,
29
- guessProviderID,
30
- getBucketPriority,
31
- normalizeModelLookup,
32
- parseRemoteModelQuery as parseOpenCodeModelQuery,
33
- formatRemoteUnavailableModel as formatOpenCodeUnavailableModel,
34
- } from "../../remote-server/model-catalog/index.js";
35
-
36
- const kiloModels = createRemoteModelCatalogModule({
37
- label: "Kilo",
38
- getClient: () => ensureServer(),
39
- maxCallbackIdLength: 90,
40
- allowCallbackSeparators: true,
41
- quickPickLimit: 24,
42
- });
43
-
44
- // A stopped server invalidates the catalog it served.
45
- onServerStop(kiloModels.clearCache);
46
-
47
- export const getOpenCodeModelCatalog = kiloModels.getCatalog;
48
- export const clearModelCatalogCache = kiloModels.clearCache;
49
- export const getOpenCodeModelInfo = kiloModels.getModelInfo;
50
- export const getOpenCodeQuickPickModels = kiloModels.getQuickPickModels;
51
- export const getOpenCodeSettingsPresentation =
52
- kiloModels.getSettingsPresentation;
53
- export const renderOpenCodeModelSummary = kiloModels.renderModelSummary;
54
- export const renderOpenCodeModelList = kiloModels.renderModelList;
55
- export const formatOpenCodeSelectionError = kiloModels.formatSelectionError;
@@ -1,42 +0,0 @@
1
- /**
2
- * Kilo one-shot agent runner — used by heartbeat & dream.
3
- *
4
- * Thin binding over the shared remote-server runner (see
5
- * `backend/remote-server/one-shot.ts` for the design notes): Kilo
6
- * supplies its server bootstrap, model-selection parser, and delivery
7
- * suffix; everything else is the shared lifecycle.
8
- */
9
-
10
- import type { OneShotAgentParams, OneShotUsage } from "../../core/types.js";
11
- import { runRemoteOneShotAgent } from "../remote-server/one-shot.js";
12
- import {
13
- ensureServer,
14
- ensureChatMcpServer,
15
- ensurePluginMcpServers,
16
- buildToolOverrides,
17
- disconnectChatMcpServer,
18
- resolveProviderID,
19
- parseStoredKiloModelSelection,
20
- KILO_SYSTEM_PROMPT_SUFFIX,
21
- errMsg,
22
- } from "./server.js";
23
-
24
- export function runOneShotAgent(
25
- params: OneShotAgentParams,
26
- ): Promise<OneShotUsage | void> {
27
- return runRemoteOneShotAgent(
28
- {
29
- label: "Kilo",
30
- systemPromptSuffix: KILO_SYSTEM_PROMPT_SUFFIX,
31
- ensureServer,
32
- parseModelSelection: parseStoredKiloModelSelection,
33
- resolveProviderID,
34
- ensureChatMcpServer,
35
- ensurePluginMcpServers,
36
- buildToolOverrides,
37
- disconnectChatMcpServer,
38
- errMsg,
39
- },
40
- params,
41
- );
42
- }
@@ -1,98 +0,0 @@
1
- /**
2
- * Kilo server lifecycle — the Kilo profile bound through
3
- * `backend/remote-server/server-bindings.ts`.
4
- *
5
- * Kilo is a fork of OpenCode with the same HTTP API, so the server spawn,
6
- * MCP registration, session creation, and provider resolution are the
7
- * shared family implementation. This module holds only what is Kilo's:
8
- * the SDK constructors, port 4097, the text-or-tools delivery contract,
9
- * and the `kilo/`-prefix model parser. The exports keep their historical
10
- * names — the models module, one-shot runner, tests, and
11
- * `vi.mock("../backend/kilo/server.js")` all address them.
12
- */
13
-
14
- import {
15
- createKiloClient,
16
- createKiloServer,
17
- type KiloClient,
18
- } from "@kilocode/sdk/v2";
19
- import {
20
- bindRemoteServer,
21
- type RemoteModelSelection,
22
- } from "../remote-server/server-bindings.js";
23
-
24
- /**
25
- * Parse the stored model-selection string into a `{providerID?, modelID}`
26
- * pair.
27
- *
28
- * Kilo model ids frequently contain `/` and `:` inside the model.id itself
29
- * (e.g. `inclusionai/ling-2.6-1t:free`, `deepseek/deepseek-v4-flash:free`).
30
- * A naive `provider/model` splitter mis-treats those vendor prefixes as
31
- * the provider, so we generally return the whole string as the model id
32
- * and let `resolveProviderID` look up the real provider from the live
33
- * catalog.
34
- *
35
- * Exception: if the value starts with the literal `kilo/` prefix
36
- * (Talon's old hint that "this is a kilo-routed model"), strip it AND
37
- * pin providerID to `"kilo"`. Otherwise the upstream Kilo router gets
38
- * `kilo/deepseek/deepseek-v4-flash:free` as the model id and concats
39
- * its own provider in front, producing
40
- * `Model not found: opencode/kilo/deepseek/deepseek-v4-flash:free`.
41
- */
42
- export function parseStoredKiloModelSelection(
43
- value: string,
44
- ): RemoteModelSelection {
45
- const trimmed = value.trim();
46
- if (trimmed.startsWith("kilo/")) {
47
- return {
48
- providerID: "kilo",
49
- modelID: trimmed.slice("kilo/".length),
50
- };
51
- }
52
- return {
53
- providerID: undefined,
54
- modelID: trimmed,
55
- };
56
- }
57
-
58
- /**
59
- * Kilo delivery model: the reply reaches the user either as a `text` part
60
- * (what most Kilo-routed models emit by default — DeepSeek, GLM,
61
- * openrouter routes) or through a delivery tool (`end_turn` / `send` /
62
- * `react`) when reply-to targeting, buttons, photos, or polls are needed.
63
- * Both routes work; the shared text-or-tools contract documents the
64
- * choice.
65
- */
66
- const kilo = bindRemoteServer<KiloClient>({
67
- label: "Kilo",
68
- defaultPort: 4097,
69
- portEnv: "KILO_PORT",
70
- deliveryContract: "text-or-tools",
71
- createClient: (baseUrl) => createKiloClient({ baseUrl, throwOnError: true }),
72
- createServer: ({ hostname, port, timeout }) =>
73
- createKiloServer({ hostname, port, timeout }),
74
- parseModelSelection: parseStoredKiloModelSelection,
75
- });
76
-
77
- export const KILO_BASE_URL = kilo.baseUrl;
78
- export const kiloSystemPromptSuffix = kilo.systemPromptSuffix;
79
- export const KILO_SYSTEM_PROMPT_SUFFIX = kilo.defaultSystemPromptSuffix;
80
- export const initKiloAgent = kilo.init;
81
- export const stopKiloServer = kilo.stop;
82
- export const {
83
- onServerStop,
84
- ensureServer,
85
- trackActiveTurn,
86
- ensureChatMcpServer,
87
- ensurePluginMcpServers,
88
- buildToolOverrides,
89
- disconnectChatMcpServer,
90
- refreshPluginMcpServers,
91
- updateSystemPrompt,
92
- ensureSession,
93
- warmSession,
94
- resolveProviderID,
95
- getConfig,
96
- getRegisteredMcpServerNames,
97
- errMsg,
98
- } = kilo;
@@ -1,37 +0,0 @@
1
- /**
2
- * Kilo session helpers — the shared `remote-server/session-helpers.ts`
3
- * bound to the Kilo client, re-exported under Kilo-named symbols for the
4
- * handler / index / test imports.
5
- */
6
-
7
- import type { KiloClient } from "@kilocode/sdk/v2";
8
- import {
9
- extractPartsSummary as extractPartsSummaryShared,
10
- extractAssistantUsage as extractAssistantUsageShared,
11
- summarizeAssistantMessages,
12
- getSessionSnapshot,
13
- type RemoteSessionSnapshot,
14
- type RemoteSessionClient,
15
- } from "../remote-server/session-helpers.js";
16
- import { ensureServer } from "./server.js";
17
-
18
- /** Snapshot of a Kilo session's lifetime + last-turn assistant info. */
19
- export type KiloSessionSnapshot = RemoteSessionSnapshot;
20
-
21
- export const extractPartsSummary = extractPartsSummaryShared;
22
- export const extractAssistantUsage = extractAssistantUsageShared;
23
-
24
- /** Summarise a batch of session messages into per-turn usage totals. */
25
- export const summarizeKiloAssistantMessages = summarizeAssistantMessages;
26
-
27
- /**
28
- * Build a {@link KiloSessionSnapshot} for the given session id.
29
- * Returns `undefined` if no session id was provided.
30
- */
31
- export async function getKiloSessionSnapshot(
32
- sessionId: string | undefined,
33
- ): Promise<KiloSessionSnapshot | undefined> {
34
- if (!sessionId) return undefined;
35
- const oc: KiloClient = await ensureServer();
36
- return getSessionSnapshot(oc as unknown as RemoteSessionClient, sessionId);
37
- }
@@ -1,53 +0,0 @@
1
- /**
2
- * OpenCode backend factory — wires OpenCode into the registry.
3
- *
4
- * Side-effect import (`import "./factory.js"` from `bootstrap.ts`) calls
5
- * `registerBackend(...)` at module load, making OpenCode available under
6
- * `config.backend === "opencode"`. The capability wiring is the shared
7
- * remote-server composition; only the bound functions are OpenCode's.
8
- */
9
-
10
- import { registerBackend } from "../../core/agent-runtime/backend-registry.js";
11
- import { createRemoteBackendFactory } from "../remote-server/factory.js";
12
- import {
13
- initOpenCodeAgent,
14
- stopOpenCodeServer,
15
- handleMessage,
16
- runOneShotAgent,
17
- getOpenCodeSessionSnapshot,
18
- resolveModel,
19
- getModelInfo,
20
- getSettingsPresentation,
21
- getProviders,
22
- getProviderModels,
23
- formatModelError,
24
- listModels,
25
- refreshPluginMcpServers,
26
- updateSystemPrompt,
27
- warmSession,
28
- } from "./index.js";
29
-
30
- registerBackend(
31
- createRemoteBackendFactory({
32
- id: "opencode",
33
- label: "OpenCode",
34
- sdkPackage: "@opencode-ai/sdk",
35
- init: initOpenCodeAgent,
36
- stop: stopOpenCodeServer,
37
- handleMessage,
38
- runOneShotAgent,
39
- getSessionSnapshot: getOpenCodeSessionSnapshot,
40
- models: {
41
- resolveModel,
42
- getModelInfo,
43
- getSettingsPresentation,
44
- getProviders,
45
- getProviderModels,
46
- formatModelError,
47
- listModels,
48
- },
49
- refreshPluginMcpServers,
50
- warmSession,
51
- updateSystemPrompt,
52
- }),
53
- );
@@ -1,2 +0,0 @@
1
- /** OpenCode message handler barrel. */
2
- export { handleMessage } from "./message.js";
@@ -1,44 +0,0 @@
1
- /**
2
- * OpenCode main message handler — the shared remote-server chat turn
3
- * bound to OpenCode's server bindings.
4
- */
5
-
6
- import type {
7
- QueryParams,
8
- QueryResult,
9
- } from "../../runtime/turn/handler-types.js";
10
- import { runRemoteChatTurn } from "../../remote-server/chat-turn.js";
11
- import {
12
- ensureServer,
13
- trackActiveTurn,
14
- ensureSession,
15
- ensureChatMcpServer,
16
- ensurePluginMcpServers,
17
- buildToolOverrides,
18
- resolveProviderID,
19
- parseStoredOpenCodeModelSelection,
20
- getConfig,
21
- opencodeSystemPromptSuffix,
22
- } from "../server.js";
23
-
24
- export function handleMessage(params: QueryParams): Promise<QueryResult> {
25
- // Assembled per call, not at module load: tests mock `../server.js`
26
- // with a partial surface and only touch the members they need.
27
- return runRemoteChatTurn(
28
- {
29
- id: "opencode",
30
- label: "OpenCode",
31
- getConfig,
32
- ensureServer,
33
- trackActiveTurn,
34
- parseModelSelection: parseStoredOpenCodeModelSelection,
35
- resolveProviderID,
36
- ensureSession,
37
- ensureChatMcpServer,
38
- ensurePluginMcpServers,
39
- buildToolOverrides,
40
- systemPromptSuffix: opencodeSystemPromptSuffix,
41
- },
42
- params,
43
- );
44
- }
@@ -1,42 +0,0 @@
1
- /**
2
- * OpenCode backend — uses the OpenCode SDK as an alternative to Claude Agent SDK.
3
- *
4
- * Re-exports from focused sub-modules:
5
- * models.ts — model catalog, search, resolution, presentation
6
- * sessions.ts — message parsing, usage summaries, snapshots
7
- * server.ts — server lifecycle, MCP, session management
8
- * handler.ts — main message handler
9
- */
10
-
11
- export {
12
- getOpenCodeModelSelectionValue,
13
- resolveOpenCodeModelInput,
14
- formatOpenCodeSelectionError,
15
- } from "./models/index.js";
16
-
17
- export {
18
- summarizeOpenCodeAssistantMessages,
19
- getOpenCodeSessionSnapshot,
20
- } from "./sessions.js";
21
-
22
- export {
23
- initOpenCodeAgent,
24
- stopOpenCodeServer,
25
- refreshPluginMcpServers,
26
- updateSystemPrompt,
27
- warmSession,
28
- } from "./server.js";
29
-
30
- export { handleMessage } from "./handler/index.js";
31
-
32
- export {
33
- resolveModel,
34
- getModelInfo,
35
- getSettingsPresentation,
36
- getProviders,
37
- getProviderModels,
38
- formatModelError,
39
- listModels,
40
- } from "./model-provider.js";
41
-
42
- export { runOneShotAgent } from "./one-shot.js";
@@ -1,36 +0,0 @@
1
- /**
2
- * OpenCode model provider — adapts the internal catalog to the Backend model
3
- * interface via the shared remote-server factory. Each export matches a
4
- * method on `Backend.models`.
5
- */
6
-
7
- import { createRemoteModelProvider } from "../remote-server/model-catalog/index.js";
8
- import {
9
- getOpenCodeModelCatalog,
10
- getOpenCodeModelInfo,
11
- getOpenCodeModelSelectionValue,
12
- resolveOpenCodeModelInput,
13
- getOpenCodeSettingsPresentation,
14
- formatOpenCodeUnavailableModel,
15
- } from "./models/index.js";
16
-
17
- const provider = createRemoteModelProvider({
18
- label: "OpenCode",
19
- getCatalog: (forceRefresh) => getOpenCodeModelCatalog(forceRefresh),
20
- getModelInfo: (id) => getOpenCodeModelInfo(id),
21
- resolveModelInput: (query, catalog) =>
22
- resolveOpenCodeModelInput(query, catalog),
23
- getSelectionValue: (model, catalog) =>
24
- getOpenCodeModelSelectionValue(model, catalog),
25
- formatUnavailableModel: (model) => formatOpenCodeUnavailableModel(model),
26
- getSettingsPresentation: (activeModel, callbackPrefix) =>
27
- getOpenCodeSettingsPresentation(activeModel, callbackPrefix),
28
- });
29
-
30
- export const resolveModel = provider.resolveModel;
31
- export const getModelInfo = provider.getModelInfo;
32
- export const getSettingsPresentation = provider.getSettingsPresentation;
33
- export const getProviders = provider.getProviders;
34
- export const getProviderModels = provider.getProviderModels;
35
- export const listModels = provider.listModels;
36
- export const formatModelError = provider.formatModelError;
@@ -1,54 +0,0 @@
1
- /**
2
- * OpenCode model catalog — binder over the shared remote-server model-catalog
3
- * module (see `backend/remote-server/model-catalog/`).
4
- *
5
- * The catalog, resolution, and presentation logic is shared with Kilo (a fork
6
- * of OpenCode with the same wire format); this file only binds the OpenCode
7
- * SDK client + presentation knobs and re-exports the result under the
8
- * historical `OpenCode*`-prefixed names.
9
- *
10
- * Knobs: OpenCode's model picker renders through Telegram inline keyboards —
11
- * callback_data caps at 64 bytes and the keyboard is tight, so quick picks
12
- * stay at 4 and only short separator-free ids are embedded raw.
13
- */
14
-
15
- import { ensureServer, onServerStop } from "../server.js";
16
- import { createRemoteModelCatalogModule } from "../../remote-server/model-catalog/index.js";
17
-
18
- export type {
19
- RemoteModelCatalogEntry as OpenCodeModelCatalogEntry,
20
- RemoteModelCatalog as OpenCodeModelCatalog,
21
- RemoteModelResolution as OpenCodeModelResolution,
22
- ModelButton,
23
- } from "../../remote-server/model-catalog/index.js";
24
- export {
25
- sortCatalogModels,
26
- getRemoteModelSelectionValue as getOpenCodeModelSelectionValue,
27
- resolveRemoteModelInput as resolveOpenCodeModelInput,
28
- guessProviderID,
29
- getBucketPriority,
30
- normalizeModelLookup,
31
- parseRemoteModelQuery as parseOpenCodeModelQuery,
32
- formatRemoteUnavailableModel as formatOpenCodeUnavailableModel,
33
- } from "../../remote-server/model-catalog/index.js";
34
-
35
- const opencodeModels = createRemoteModelCatalogModule({
36
- label: "OpenCode",
37
- getClient: () => ensureServer(),
38
- maxCallbackIdLength: 48,
39
- allowCallbackSeparators: false,
40
- quickPickLimit: 4,
41
- });
42
-
43
- // A stopped server invalidates the catalog it served.
44
- onServerStop(opencodeModels.clearCache);
45
-
46
- export const getOpenCodeModelCatalog = opencodeModels.getCatalog;
47
- export const clearModelCatalogCache = opencodeModels.clearCache;
48
- export const getOpenCodeModelInfo = opencodeModels.getModelInfo;
49
- export const getOpenCodeQuickPickModels = opencodeModels.getQuickPickModels;
50
- export const getOpenCodeSettingsPresentation =
51
- opencodeModels.getSettingsPresentation;
52
- export const renderOpenCodeModelSummary = opencodeModels.renderModelSummary;
53
- export const renderOpenCodeModelList = opencodeModels.renderModelList;
54
- export const formatOpenCodeSelectionError = opencodeModels.formatSelectionError;
@@ -1,42 +0,0 @@
1
- /**
2
- * OpenCode one-shot agent runner — used by heartbeat & dream.
3
- *
4
- * Thin binding over the shared remote-server runner (see
5
- * `backend/remote-server/one-shot.ts` for the design notes): OpenCode
6
- * supplies its server bootstrap, model-selection parser, and delivery
7
- * suffix; everything else is the shared lifecycle.
8
- */
9
-
10
- import type { OneShotAgentParams, OneShotUsage } from "../../core/types.js";
11
- import { runRemoteOneShotAgent } from "../remote-server/one-shot.js";
12
- import {
13
- ensureServer,
14
- ensureChatMcpServer,
15
- ensurePluginMcpServers,
16
- buildToolOverrides,
17
- disconnectChatMcpServer,
18
- resolveProviderID,
19
- parseStoredOpenCodeModelSelection,
20
- OPENCODE_SYSTEM_PROMPT_SUFFIX,
21
- errMsg,
22
- } from "./server.js";
23
-
24
- export function runOneShotAgent(
25
- params: OneShotAgentParams,
26
- ): Promise<OneShotUsage | void> {
27
- return runRemoteOneShotAgent(
28
- {
29
- label: "OpenCode",
30
- systemPromptSuffix: OPENCODE_SYSTEM_PROMPT_SUFFIX,
31
- ensureServer,
32
- parseModelSelection: parseStoredOpenCodeModelSelection,
33
- resolveProviderID,
34
- ensureChatMcpServer,
35
- ensurePluginMcpServers,
36
- buildToolOverrides,
37
- disconnectChatMcpServer,
38
- errMsg,
39
- },
40
- params,
41
- );
42
- }
@@ -1,80 +0,0 @@
1
- /**
2
- * OpenCode server lifecycle — the OpenCode profile bound through
3
- * `backend/remote-server/server-bindings.ts`.
4
- *
5
- * The server spawn, MCP registration, session creation, and provider
6
- * resolution are the shared remote-server family implementation (Kilo is
7
- * a fork with the same HTTP API). This module holds only what is
8
- * OpenCode's: the SDK constructors, port 4096, the text-preferred
9
- * delivery contract, and the fuzzy `provider/model` parser. The exports
10
- * keep their historical names — the models module, one-shot runner,
11
- * tests, and `vi.mock("../backend/opencode/server.js")` all address them.
12
- */
13
-
14
- import {
15
- createOpencodeClient,
16
- createOpencodeServer,
17
- type OpencodeClient,
18
- } from "@opencode-ai/sdk/v2";
19
- import {
20
- normalizeModelLookup,
21
- parseRemoteModelQuery,
22
- } from "../remote-server/model-catalog/index.js";
23
- import {
24
- bindRemoteServer,
25
- type RemoteModelSelection,
26
- } from "../remote-server/server-bindings.js";
27
-
28
- /**
29
- * Parse the stored model-selection string into a `{providerID?, modelID}`
30
- * pair. The parser is fuzzy — it tries to extract a provider hint from the
31
- * prefix while preserving the full model id when ambiguous. See
32
- * `remote-server/model-catalog/` for the underlying `parseRemoteModelQuery`.
33
- */
34
- export function parseStoredOpenCodeModelSelection(
35
- value: string,
36
- ): RemoteModelSelection {
37
- const { providerQuery, modelQuery } = parseRemoteModelQuery(value);
38
- return {
39
- providerID: providerQuery ? normalizeModelLookup(providerQuery) : undefined,
40
- modelID: modelQuery,
41
- };
42
- }
43
-
44
- // Text-preferred delivery: plain assistant text is the reply; tools only
45
- // for genuine side effects. Single-sourced from the shared contract
46
- // templates (prompts/system/contract-text-preferred.md).
47
- const opencode = bindRemoteServer<OpencodeClient>({
48
- label: "OpenCode",
49
- defaultPort: 4096,
50
- portEnv: "OPENCODE_PORT",
51
- deliveryContract: "text-preferred",
52
- createClient: (baseUrl) =>
53
- createOpencodeClient({ baseUrl, throwOnError: true }),
54
- createServer: ({ hostname, port, timeout }) =>
55
- createOpencodeServer({ hostname, port, timeout }),
56
- parseModelSelection: parseStoredOpenCodeModelSelection,
57
- });
58
-
59
- export const OPENCODE_BASE_URL = opencode.baseUrl;
60
- export const opencodeSystemPromptSuffix = opencode.systemPromptSuffix;
61
- export const OPENCODE_SYSTEM_PROMPT_SUFFIX = opencode.defaultSystemPromptSuffix;
62
- export const initOpenCodeAgent = opencode.init;
63
- export const stopOpenCodeServer = opencode.stop;
64
- export const {
65
- onServerStop,
66
- ensureServer,
67
- trackActiveTurn,
68
- ensureChatMcpServer,
69
- ensurePluginMcpServers,
70
- buildToolOverrides,
71
- disconnectChatMcpServer,
72
- refreshPluginMcpServers,
73
- updateSystemPrompt,
74
- ensureSession,
75
- warmSession,
76
- resolveProviderID,
77
- getConfig,
78
- getRegisteredMcpServerNames,
79
- errMsg,
80
- } = opencode;
@@ -1,35 +0,0 @@
1
- /**
2
- * OpenCode session helpers — the shared `remote-server/session-helpers.ts`
3
- * bound to the OpenCode client, re-exported under OpenCode-named symbols
4
- * for the handler / index / test imports.
5
- */
6
-
7
- import type { OpencodeClient } from "@opencode-ai/sdk/v2";
8
- import {
9
- extractPartsSummary as extractPartsSummaryShared,
10
- summarizeAssistantMessages,
11
- getSessionSnapshot,
12
- type RemoteSessionSnapshot,
13
- type RemoteSessionClient,
14
- } from "../remote-server/session-helpers.js";
15
- import { ensureServer } from "./server.js";
16
-
17
- /** Snapshot of an OpenCode session's lifetime + last-turn assistant info. */
18
- export type OpenCodeSessionSnapshot = RemoteSessionSnapshot;
19
-
20
- export const extractPartsSummary = extractPartsSummaryShared;
21
-
22
- /** Summarise a batch of session messages into per-turn usage totals. */
23
- export const summarizeOpenCodeAssistantMessages = summarizeAssistantMessages;
24
-
25
- /**
26
- * Build an {@link OpenCodeSessionSnapshot} for the given session id.
27
- * Returns `undefined` if no session id was provided.
28
- */
29
- export async function getOpenCodeSessionSnapshot(
30
- sessionId: string | undefined,
31
- ): Promise<OpenCodeSessionSnapshot | undefined> {
32
- if (!sessionId) return undefined;
33
- const oc: OpencodeClient = await ensureServer();
34
- return getSessionSnapshot(oc as unknown as RemoteSessionClient, sessionId);
35
- }