Skip to content

Commit 181a50e

Browse files
committed
refactor: remove bundled channel discovery leaks
1 parent 604e16c commit 181a50e

12 files changed

Lines changed: 457 additions & 744 deletions

src/agents/openai-ws-stream.test.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,9 @@ describe("convertTools", () => {
512512
parameters: { type: "object", properties: {}, additionalProperties: false },
513513
},
514514
];
515-
const result = convertTools(tools as Parameters<typeof convertTools>[0], { strict: true });
515+
const result = convertTools(tools as unknown as Parameters<typeof convertTools>[0], {
516+
strict: true,
517+
});
516518

517519
expect(result[0]).toEqual({
518520
type: "function",
@@ -540,7 +542,9 @@ describe("convertTools", () => {
540542
},
541543
},
542544
];
543-
const result = convertTools(tools as Parameters<typeof convertTools>[0], { strict: true });
545+
const result = convertTools(tools as unknown as Parameters<typeof convertTools>[0], {
546+
strict: true,
547+
});
544548

545549
expect(result[0]).toEqual({
546550
type: "function",

src/channels/chat-meta-shared.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { listBundledPluginMetadata } from "../plugins/bundled-plugin-metadata.js";
1+
import { listChannelCatalogEntries } from "../plugins/channel-catalog-registry.js";
22
import type { PluginPackageChannel } from "../plugins/manifest.js";
33
import { CHAT_CHANNEL_ORDER, type ChatChannelId } from "./ids.js";
44
import type { ChannelMeta } from "./plugins/types.js";
@@ -64,14 +64,8 @@ function toChatChannelMeta(params: {
6464
export function buildChatChannelMetaById(): Record<ChatChannelId, ChatChannelMeta> {
6565
const entries = new Map<ChatChannelId, ChatChannelMeta>();
6666

67-
for (const entry of listBundledPluginMetadata({
68-
includeChannelConfigs: true,
69-
includeSyntheticChannelConfigs: false,
70-
})) {
71-
const channel =
72-
entry.packageManifest && "channel" in entry.packageManifest
73-
? entry.packageManifest.channel
74-
: undefined;
67+
for (const entry of listChannelCatalogEntries({ origin: "bundled" })) {
68+
const channel = entry.channel;
7569
if (!channel) {
7670
continue;
7771
}

src/channels/ids.test.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expect, it } from "vitest";
2-
import { listBundledPluginMetadata } from "../plugins/bundled-plugin-metadata.js";
2+
import { listChannelCatalogEntries } from "../plugins/channel-catalog-registry.js";
33
import {
44
CHAT_CHANNEL_ALIASES,
55
CHAT_CHANNEL_ORDER,
@@ -10,14 +10,8 @@ import {
1010
function collectBundledChatChannelAliases(): Record<string, ChatChannelId> {
1111
const aliases = new Map<string, ChatChannelId>();
1212

13-
for (const entry of listBundledPluginMetadata({
14-
includeChannelConfigs: true,
15-
includeSyntheticChannelConfigs: false,
16-
})) {
17-
const channel =
18-
entry.packageManifest && "channel" in entry.packageManifest
19-
? entry.packageManifest.channel
20-
: undefined;
13+
for (const entry of listChannelCatalogEntries({ origin: "bundled" })) {
14+
const channel = entry.channel;
2115
const rawId = channel?.id?.trim();
2216
if (!rawId || !CHAT_CHANNEL_ORDER.includes(rawId)) {
2317
continue;

src/channels/ids.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { listBundledPluginMetadata } from "../plugins/bundled-plugin-metadata.js";
1+
import { listChannelCatalogEntries } from "../plugins/channel-catalog-registry.js";
22

33
export type ChatChannelId = string;
44

@@ -14,17 +14,10 @@ function normalizeChannelKey(raw?: string | null): string | undefined {
1414
}
1515

1616
function listBundledChatChannelEntries(): BundledChatChannelEntry[] {
17-
return listBundledPluginMetadata({
18-
includeChannelConfigs: false,
19-
includeSyntheticChannelConfigs: false,
20-
})
21-
.flatMap((entry) => {
22-
const channel =
23-
entry.packageManifest && "channel" in entry.packageManifest
24-
? entry.packageManifest.channel
25-
: undefined;
26-
const id = normalizeChannelKey(channel?.id);
27-
if (!channel || !id) {
17+
return listChannelCatalogEntries({ origin: "bundled" })
18+
.flatMap(({ channel }) => {
19+
const id = normalizeChannelKey(channel.id);
20+
if (!id) {
2821
return [];
2922
}
3023
const aliases = (channel.aliases ?? [])

src/channels/plugins/bundled-ids.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
import { listBundledPluginMetadata } from "../../plugins/bundled-plugin-metadata.js";
1+
import { listChannelCatalogEntries } from "../../plugins/channel-catalog-registry.js";
22

3-
export const BUNDLED_CHANNEL_PLUGIN_IDS = listBundledPluginMetadata({
4-
includeChannelConfigs: false,
5-
includeSyntheticChannelConfigs: false,
6-
})
7-
.filter(({ manifest }) => Array.isArray(manifest.channels) && manifest.channels.length > 0)
8-
.map(({ manifest }) => manifest.id)
3+
export const BUNDLED_CHANNEL_PLUGIN_IDS = listChannelCatalogEntries({ origin: "bundled" })
4+
.map((entry) => entry.pluginId)
95
.toSorted((left, right) => left.localeCompare(right));
106

117
export function listBundledChannelPluginIds(): string[] {

src/channels/plugins/bundled.ts

Lines changed: 7 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import type {
88
BundledChannelEntryContract,
99
BundledChannelSetupEntryContract,
1010
} from "../../plugin-sdk/channel-entry-contract.js";
11-
import { discoverOpenClawPlugins } from "../../plugins/discovery.js";
1211
import { loadPluginManifestRegistry } from "../../plugins/manifest-registry.js";
1312
import type { PluginRuntime } from "../../plugins/runtime/types.js";
1413
import {
@@ -24,20 +23,6 @@ type GeneratedBundledChannelEntry = {
2423
setupEntry?: BundledChannelSetupEntryContract;
2524
};
2625

27-
type BundledChannelDiscoveryCandidate = {
28-
rootDir: string;
29-
packageManifest?: {
30-
extensions?: string[];
31-
};
32-
};
33-
34-
const BUNDLED_CHANNEL_ENTRY_BASENAMES = [
35-
"channel-entry.ts",
36-
"channel-entry.mts",
37-
"channel-entry.js",
38-
"channel-entry.mjs",
39-
] as const;
40-
4126
const log = createSubsystemLogger("channels");
4227
const nodeRequire = createRequire(import.meta.url);
4328

@@ -155,53 +140,19 @@ function resolveCompiledBundledModulePath(modulePath: string): string {
155140
: modulePath;
156141
}
157142

158-
function resolvePreferredBundledChannelSource(
159-
candidate: BundledChannelDiscoveryCandidate,
160-
manifest: ReturnType<typeof loadPluginManifestRegistry>["plugins"][number],
161-
): string {
162-
for (const basename of BUNDLED_CHANNEL_ENTRY_BASENAMES) {
163-
const preferred = resolveCompiledBundledModulePath(path.resolve(candidate.rootDir, basename));
164-
if (fs.existsSync(preferred)) {
165-
return preferred;
166-
}
167-
}
168-
const declaredEntry = candidate.packageManifest?.extensions?.find(
169-
(entry): entry is string => typeof entry === "string" && entry.trim().length > 0,
170-
);
171-
if (declaredEntry) {
172-
return resolveCompiledBundledModulePath(path.resolve(candidate.rootDir, declaredEntry));
173-
}
174-
return resolveCompiledBundledModulePath(manifest.source);
175-
}
176-
177143
function loadGeneratedBundledChannelEntries(): readonly GeneratedBundledChannelEntry[] {
178-
const discovery = discoverOpenClawPlugins({ cache: false });
179-
const manifestRegistry = loadPluginManifestRegistry({
180-
cache: false,
181-
config: {},
182-
candidates: discovery.candidates,
183-
diagnostics: discovery.diagnostics,
184-
});
185-
const manifestByRoot = new Map(
186-
manifestRegistry.plugins.map((plugin) => [plugin.rootDir, plugin] as const),
187-
);
188-
const seenIds = new Set<string>();
144+
const manifestRegistry = loadPluginManifestRegistry({ cache: false, config: {} });
189145
const entries: GeneratedBundledChannelEntry[] = [];
190146

191-
for (const candidate of discovery.candidates) {
192-
const manifest = manifestByRoot.get(candidate.rootDir);
193-
if (!manifest || manifest.origin !== "bundled" || manifest.channels.length === 0) {
194-
continue;
195-
}
196-
if (seenIds.has(manifest.id)) {
147+
for (const manifest of manifestRegistry.plugins) {
148+
if (manifest.origin !== "bundled" || manifest.channels.length === 0) {
197149
continue;
198150
}
199-
seenIds.add(manifest.id);
200151

201152
try {
202-
const sourcePath = resolvePreferredBundledChannelSource(candidate, manifest);
153+
const sourcePath = resolveCompiledBundledModulePath(manifest.source);
203154
const entry = resolveChannelPluginModuleEntry(
204-
loadBundledModule(sourcePath, candidate.rootDir),
155+
loadBundledModule(sourcePath, manifest.rootDir),
205156
);
206157
if (!entry) {
207158
log.warn(
@@ -213,7 +164,7 @@ function loadGeneratedBundledChannelEntries(): readonly GeneratedBundledChannelE
213164
? resolveChannelSetupModuleEntry(
214165
loadBundledModule(
215166
resolveCompiledBundledModulePath(manifest.setupSource),
216-
candidate.rootDir,
167+
manifest.rootDir,
217168
),
218169
)
219170
: null;
@@ -225,7 +176,7 @@ function loadGeneratedBundledChannelEntries(): readonly GeneratedBundledChannelE
225176
} catch (error) {
226177
const detail = error instanceof Error ? error.message : String(error);
227178
log.warn(
228-
`[channels] failed to load bundled channel ${manifest.id} from ${candidate.source}: ${detail}`,
179+
`[channels] failed to load bundled channel ${manifest.id} from ${manifest.source}: ${detail}`,
229180
);
230181
}
231182
}

0 commit comments

Comments
 (0)