@mcoda/agent-setup 0.1.66

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 (52) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE +21 -0
  3. package/README.md +14 -0
  4. package/dist/client.d.ts +20 -0
  5. package/dist/client.d.ts.map +1 -0
  6. package/dist/client.js +83 -0
  7. package/dist/defaultStages.d.ts +18 -0
  8. package/dist/defaultStages.d.ts.map +1 -0
  9. package/dist/defaultStages.js +56 -0
  10. package/dist/headless/catalog.d.ts +24 -0
  11. package/dist/headless/catalog.d.ts.map +1 -0
  12. package/dist/headless/catalog.js +231 -0
  13. package/dist/headless/index.d.ts +4 -0
  14. package/dist/headless/index.d.ts.map +1 -0
  15. package/dist/headless/index.js +2 -0
  16. package/dist/headless/normalization.d.ts +12 -0
  17. package/dist/headless/normalization.d.ts.map +1 -0
  18. package/dist/headless/normalization.js +105 -0
  19. package/dist/index.d.ts +5 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +4 -0
  22. package/dist/react/index.d.ts +68 -0
  23. package/dist/react/index.d.ts.map +1 -0
  24. package/dist/react/index.js +295 -0
  25. package/dist/server/cliRuntime.d.ts +12 -0
  26. package/dist/server/cliRuntime.d.ts.map +1 -0
  27. package/dist/server/cliRuntime.js +130 -0
  28. package/dist/server/httpHandlers.d.ts +13 -0
  29. package/dist/server/httpHandlers.d.ts.map +1 -0
  30. package/dist/server/httpHandlers.js +130 -0
  31. package/dist/server/inMemoryRuntime.d.ts +8 -0
  32. package/dist/server/inMemoryRuntime.d.ts.map +1 -0
  33. package/dist/server/inMemoryRuntime.js +89 -0
  34. package/dist/server/index.d.ts +8 -0
  35. package/dist/server/index.d.ts.map +1 -0
  36. package/dist/server/index.js +6 -0
  37. package/dist/server/programmaticRuntime.d.ts +15 -0
  38. package/dist/server/programmaticRuntime.d.ts.map +1 -0
  39. package/dist/server/programmaticRuntime.js +136 -0
  40. package/dist/server/service.d.ts +3 -0
  41. package/dist/server/service.d.ts.map +1 -0
  42. package/dist/server/service.js +143 -0
  43. package/dist/server/settingsStore.d.ts +3 -0
  44. package/dist/server/settingsStore.d.ts.map +1 -0
  45. package/dist/server/settingsStore.js +34 -0
  46. package/dist/types.d.ts +207 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +1 -0
  49. package/examples/express-server/README.md +34 -0
  50. package/examples/nextjs-mcoda-agent-setup/README.md +63 -0
  51. package/examples/vite-react-mcoda-agent-setup/README.md +26 -0
  52. package/package.json +84 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## 0.1.66
4
+
5
+ - Initial agent setup SDK package.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 bekir dag
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,14 @@
1
+ # @mcoda/agent-setup
2
+
3
+ Turnkey mcoda/mswarm agent setup SDK for applications.
4
+
5
+ The package provides:
6
+
7
+ - headless catalog and assignment utilities
8
+ - a typed HTTP client
9
+ - framework-agnostic server service helpers
10
+ - a default programmatic mcoda runtime adapter
11
+ - an optional React setup page
12
+
13
+ The default server runtime uses mcoda package APIs directly and does not require
14
+ a preinstalled or configured `mcoda` CLI/client tool.
@@ -0,0 +1,20 @@
1
+ import type { McodaAgentSetupClient } from "./types.js";
2
+ type FetchLike = (input: string | URL, init?: {
3
+ method?: string;
4
+ headers?: Record<string, string>;
5
+ body?: string;
6
+ }) => Promise<{
7
+ ok: boolean;
8
+ status: number;
9
+ statusText: string;
10
+ json(): Promise<unknown>;
11
+ text(): Promise<string>;
12
+ }>;
13
+ export interface CreateMcodaAgentSetupClientInput {
14
+ baseUrl: string;
15
+ getAuthHeaders?: (() => Promise<Record<string, string>> | Record<string, string>) | Record<string, string>;
16
+ fetch?: FetchLike;
17
+ }
18
+ export declare function createMcodaAgentSetupClient(input: CreateMcodaAgentSetupClientInput): McodaAgentSetupClient;
19
+ export {};
20
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EAGtB,MAAM,YAAY,CAAC;AAEpB,KAAK,SAAS,GAAG,CACf,KAAK,EAAE,MAAM,GAAG,GAAG,EACnB,IAAI,CAAC,EAAE;IACL,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,KACE,OAAO,CAAC;IACX,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACzB,CAAC,CAAC;AAEH,MAAM,WAAW,gCAAgC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EACX,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAChE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,gCAAgC,GACtC,qBAAqB,CAwFvB"}
package/dist/client.js ADDED
@@ -0,0 +1,83 @@
1
+ export function createMcodaAgentSetupClient(input) {
2
+ const baseUrl = input.baseUrl.replace(/\/+$/, "");
3
+ const fetchImpl = input.fetch ?? globalThis.fetch;
4
+ if (!fetchImpl) {
5
+ throw new Error("fetch is required to create a mcoda agent setup client");
6
+ }
7
+ const requestJson = async (path, init = {}) => {
8
+ const headers = {
9
+ accept: "application/json",
10
+ ...(await resolveAuthHeaders(input.getAuthHeaders)),
11
+ };
12
+ let body;
13
+ if (init.body !== undefined) {
14
+ headers["content-type"] = "application/json";
15
+ body = JSON.stringify(init.body);
16
+ }
17
+ const response = await fetchImpl(`${baseUrl}${path}`, {
18
+ method: init.method ?? "GET",
19
+ headers,
20
+ body,
21
+ });
22
+ if (!response.ok) {
23
+ let message = `${response.status} ${response.statusText}`;
24
+ try {
25
+ const payload = await response.json();
26
+ if (payload &&
27
+ typeof payload === "object" &&
28
+ "error" in payload &&
29
+ typeof payload.error === "string") {
30
+ message = payload.error;
31
+ }
32
+ }
33
+ catch {
34
+ const text = await response.text().catch(() => "");
35
+ if (text.trim())
36
+ message = text.trim();
37
+ }
38
+ throw new Error(`mcoda agent setup request failed: ${message}`);
39
+ }
40
+ return (await response.json());
41
+ };
42
+ return {
43
+ fetchSnapshot: () => requestJson("/agent-settings"),
44
+ configureMswarmApiKey: (request) => requestJson("/mswarm-api-key", {
45
+ method: "POST",
46
+ body: {
47
+ mswarm_api_key: request.apiKey,
48
+ reason_code: request.reasonCode,
49
+ metadata: request.metadata,
50
+ },
51
+ }),
52
+ syncAgents: (request = {}) => requestJson("/agents/sync", {
53
+ method: "POST",
54
+ body: {
55
+ reason_code: request.reasonCode,
56
+ metadata: request.metadata,
57
+ },
58
+ }),
59
+ updateAssignments: (request) => requestJson("/agent-settings", {
60
+ method: "PATCH",
61
+ body: {
62
+ assignments: request.assignments,
63
+ reason_code: request.reasonCode,
64
+ metadata: request.metadata,
65
+ },
66
+ }),
67
+ testAgent: (request) => requestJson("/agents/test", {
68
+ method: "POST",
69
+ body: {
70
+ slug: request.slug,
71
+ prompt: request.prompt,
72
+ timeout_ms: request.timeoutMs,
73
+ },
74
+ }),
75
+ };
76
+ }
77
+ async function resolveAuthHeaders(input) {
78
+ if (!input)
79
+ return {};
80
+ if (typeof input === "function")
81
+ return input();
82
+ return input;
83
+ }
@@ -0,0 +1,18 @@
1
+ export declare const defaultMcodaStageDefinitions: ({
2
+ stageKey: string;
3
+ displayName: string;
4
+ description: string;
5
+ defaultAgentSlug: null;
6
+ recommendedUsage: string;
7
+ preferredSource: "cloud_or_self_hosted";
8
+ nullable: false;
9
+ } | {
10
+ stageKey: string;
11
+ displayName: string;
12
+ description: string;
13
+ defaultAgentSlug: null;
14
+ recommendedUsage: string;
15
+ preferredSource: "cloud_or_self_hosted";
16
+ nullable: true;
17
+ })[];
18
+ //# sourceMappingURL=defaultStages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaultStages.d.ts","sourceRoot":"","sources":["../src/defaultStages.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;IAuDP,CAAC"}
@@ -0,0 +1,56 @@
1
+ export const defaultMcodaStageDefinitions = [
2
+ {
3
+ stageKey: "translation",
4
+ displayName: "Translation",
5
+ description: "Translate source text into the application's working language.",
6
+ defaultAgentSlug: null,
7
+ recommendedUsage: "translation",
8
+ preferredSource: "cloud_or_self_hosted",
9
+ nullable: false,
10
+ },
11
+ {
12
+ stageKey: "summarization",
13
+ displayName: "Summarization",
14
+ description: "Create concise summaries and digests.",
15
+ defaultAgentSlug: null,
16
+ recommendedUsage: "summarization",
17
+ preferredSource: "cloud_or_self_hosted",
18
+ nullable: false,
19
+ },
20
+ {
21
+ stageKey: "classification",
22
+ displayName: "Classification",
23
+ description: "Classify text into product-specific categories.",
24
+ defaultAgentSlug: null,
25
+ recommendedUsage: "classification",
26
+ preferredSource: "cloud_or_self_hosted",
27
+ nullable: false,
28
+ },
29
+ {
30
+ stageKey: "extraction",
31
+ displayName: "Entity Extraction",
32
+ description: "Extract structured entities or fields.",
33
+ defaultAgentSlug: null,
34
+ recommendedUsage: "extraction",
35
+ preferredSource: "cloud_or_self_hosted",
36
+ nullable: false,
37
+ },
38
+ {
39
+ stageKey: "reasoning",
40
+ displayName: "Reasoning",
41
+ description: "Run deeper analysis where simple classification is not enough.",
42
+ defaultAgentSlug: null,
43
+ recommendedUsage: "reasoning",
44
+ preferredSource: "cloud_or_self_hosted",
45
+ nullable: true,
46
+ },
47
+ {
48
+ stageKey: "guardrail",
49
+ displayName: "Guardrail Review",
50
+ description: "Validate output quality, policy, schema, and safety constraints.",
51
+ defaultAgentSlug: null,
52
+ recommendedUsage: "guardrail",
53
+ preferredSource: "cloud_or_self_hosted",
54
+ nullable: true,
55
+ },
56
+ ];
@@ -0,0 +1,24 @@
1
+ import type { McodaAgentCatalogEntry, McodaSelfHostedServer } from "../types.js";
2
+ export declare function isCloudAgent(agent: McodaAgentCatalogEntry): boolean;
3
+ export declare function isSelfHostedAgent(agent: McodaAgentCatalogEntry): boolean;
4
+ export declare function syncedCloudSlug(agent: McodaAgentCatalogEntry): string;
5
+ export declare function syncedSelfHostedSlug(agent: McodaAgentCatalogEntry): string;
6
+ export declare function mergeCatalogEntries(local: McodaAgentCatalogEntry, catalog?: McodaAgentCatalogEntry): McodaAgentCatalogEntry;
7
+ export declare function buildCloudAgentOptions(localAgents: McodaAgentCatalogEntry[], cloudCatalogAgents: McodaAgentCatalogEntry[]): McodaAgentCatalogEntry[];
8
+ export declare function buildSelfHostedServerOptions(localAgents: McodaAgentCatalogEntry[], remoteAgents: McodaAgentCatalogEntry[]): McodaSelfHostedServer[];
9
+ export declare function filterAgentOptions(agents: McodaAgentCatalogEntry[], query: string): McodaAgentCatalogEntry[];
10
+ export declare function resolveRunnableSelectionSlug(slug: string, localAgents: McodaAgentCatalogEntry[]): string;
11
+ export declare function getVirtualAgentWindow<T>(items: T[], input: {
12
+ scrollTop: number;
13
+ rowHeight: number;
14
+ viewportHeight: number;
15
+ overscan?: number;
16
+ }): {
17
+ startIndex: number;
18
+ endIndex: number;
19
+ items: T[];
20
+ beforeHeight: number;
21
+ afterHeight: number;
22
+ totalHeight: number;
23
+ };
24
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/headless/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EACtB,qBAAqB,EACtB,MAAM,aAAa,CAAC;AAkBrB,wBAAgB,YAAY,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAMnE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAOxE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAIrE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAI1E;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,sBAAsB,EAC7B,OAAO,CAAC,EAAE,sBAAsB,GAC/B,sBAAsB,CA6BxB;AAED,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,sBAAsB,EAAE,EACrC,kBAAkB,EAAE,sBAAsB,EAAE,GAC3C,sBAAsB,EAAE,CAY1B;AAED,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,sBAAsB,EAAE,EACrC,YAAY,EAAE,sBAAsB,EAAE,GACrC,qBAAqB,EAAE,CAoCzB;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,sBAAsB,EAAE,EAChC,KAAK,EAAE,MAAM,GACZ,sBAAsB,EAAE,CA6B1B;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,sBAAsB,EAAE,GACpC,MAAM,CAkBR;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE;IACL,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA;IACD,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB,CAiBA"}
@@ -0,0 +1,231 @@
1
+ const CLOUD_PREFIX = "mswarm-cloud-";
2
+ const SELF_HOSTED_PREFIX = "mswarm-self-hosted-";
3
+ const normalizeSlugPart = (value) => value
4
+ .trim()
5
+ .toLowerCase()
6
+ .replace(/[^a-z0-9]+/g, "-")
7
+ .replace(/^-+|-+$/g, "");
8
+ const lower = (value) => value?.trim().toLowerCase() ?? "";
9
+ const truthyStrings = (values) => values.map((value) => value?.trim() ?? "").filter(Boolean);
10
+ export function isCloudAgent(agent) {
11
+ return (agent.source === "cloud_catalog" ||
12
+ agent.managedKind === "cloud" ||
13
+ agent.slug.startsWith(CLOUD_PREFIX));
14
+ }
15
+ export function isSelfHostedAgent(agent) {
16
+ return (agent.source === "self_hosted_catalog" ||
17
+ agent.managedKind === "self_hosted" ||
18
+ agent.slug.startsWith(SELF_HOSTED_PREFIX) ||
19
+ Boolean(agent.nodeId || agent.serverName || agent.serverId));
20
+ }
21
+ export function syncedCloudSlug(agent) {
22
+ if (agent.slug.startsWith(CLOUD_PREFIX))
23
+ return agent.slug;
24
+ const remote = agent.remoteSlug ?? agent.slug;
25
+ return `${CLOUD_PREFIX}${normalizeSlugPart(remote) || "agent"}`;
26
+ }
27
+ export function syncedSelfHostedSlug(agent) {
28
+ if (agent.slug.startsWith(SELF_HOSTED_PREFIX))
29
+ return agent.slug;
30
+ const remote = agent.remoteSlug ?? agent.slug;
31
+ return `${SELF_HOSTED_PREFIX}${normalizeSlugPart(remote) || "agent"}`;
32
+ }
33
+ export function mergeCatalogEntries(local, catalog) {
34
+ if (!catalog)
35
+ return local;
36
+ return {
37
+ ...catalog,
38
+ ...local,
39
+ displayName: local.displayName ?? catalog.displayName,
40
+ provider: local.provider ?? catalog.provider,
41
+ adapter: local.adapter ?? catalog.adapter,
42
+ model: local.model ?? catalog.model,
43
+ defaultModel: local.defaultModel ?? catalog.defaultModel,
44
+ healthStatus: local.healthStatus ?? catalog.healthStatus,
45
+ supportsTools: local.supportsTools ?? catalog.supportsTools,
46
+ rating: local.rating ?? catalog.rating,
47
+ reasoningRating: local.reasoningRating ?? catalog.reasoningRating,
48
+ maxComplexity: local.maxComplexity ?? catalog.maxComplexity,
49
+ costPerMillion: local.costPerMillion ?? catalog.costPerMillion,
50
+ contextWindow: local.contextWindow ?? catalog.contextWindow,
51
+ maxOutputTokens: local.maxOutputTokens ?? catalog.maxOutputTokens,
52
+ bestUsage: local.bestUsage ?? catalog.bestUsage,
53
+ capabilities: local.capabilities?.length
54
+ ? local.capabilities
55
+ : catalog.capabilities,
56
+ metadata: {
57
+ ...(catalog.metadata ?? {}),
58
+ ...(local.metadata ?? {}),
59
+ },
60
+ source: local.source,
61
+ synced: true,
62
+ };
63
+ }
64
+ export function buildCloudAgentOptions(localAgents, cloudCatalogAgents) {
65
+ const catalogByLocalSlug = new Map(cloudCatalogAgents.map((agent) => [syncedCloudSlug(agent), agent]));
66
+ const synced = localAgents
67
+ .filter(isCloudAgent)
68
+ .map((agent) => mergeCatalogEntries(agent, catalogByLocalSlug.get(agent.slug)));
69
+ const localSlugs = new Set(synced.map((agent) => agent.slug));
70
+ const unsynced = cloudCatalogAgents
71
+ .filter((agent) => !localSlugs.has(syncedCloudSlug(agent)))
72
+ .map((agent) => ({ ...agent, synced: false }));
73
+ return sortAgents([...synced, ...unsynced]);
74
+ }
75
+ export function buildSelfHostedServerOptions(localAgents, remoteAgents) {
76
+ const remoteByLocalSlug = new Map(remoteAgents.map((agent) => [syncedSelfHostedSlug(agent), agent]));
77
+ const combined = [
78
+ ...localAgents
79
+ .filter(isSelfHostedAgent)
80
+ .map((agent) => mergeCatalogEntries(agent, remoteByLocalSlug.get(agent.slug))),
81
+ ...remoteAgents
82
+ .filter((agent) => !localAgents.some((local) => local.slug === syncedSelfHostedSlug(agent)))
83
+ .map((agent) => ({ ...agent, synced: false })),
84
+ ];
85
+ const servers = new Map();
86
+ for (const agent of combined) {
87
+ const server = resolveSelfHostedServer(agent);
88
+ const existing = servers.get(server.id);
89
+ if (existing) {
90
+ existing.agents.push(agent);
91
+ existing.agentCount = existing.agents.length;
92
+ existing.status = mergeServerStatus(existing.status, server.status);
93
+ continue;
94
+ }
95
+ servers.set(server.id, {
96
+ ...server,
97
+ agents: [agent],
98
+ agentCount: 1,
99
+ });
100
+ }
101
+ return Array.from(servers.values())
102
+ .map((server) => ({
103
+ ...server,
104
+ agents: sortAgents(server.agents),
105
+ }))
106
+ .sort((left, right) => left.label.localeCompare(right.label));
107
+ }
108
+ export function filterAgentOptions(agents, query) {
109
+ const terms = query
110
+ .trim()
111
+ .toLowerCase()
112
+ .split(/\s+/)
113
+ .filter(Boolean);
114
+ if (!terms.length)
115
+ return sortAgents(agents);
116
+ return sortAgents(agents.filter((agent) => {
117
+ const haystack = [
118
+ agent.displayName,
119
+ agent.slug,
120
+ agent.remoteSlug,
121
+ agent.model,
122
+ agent.defaultModel,
123
+ agent.provider,
124
+ agent.adapter,
125
+ agent.healthStatus,
126
+ agent.bestUsage,
127
+ agent.serverName,
128
+ agent.serverLabel,
129
+ agent.nodeId,
130
+ ...(agent.capabilities ?? []),
131
+ ]
132
+ .map(lower)
133
+ .join(" ");
134
+ return terms.every((term) => haystack.includes(term));
135
+ }));
136
+ }
137
+ export function resolveRunnableSelectionSlug(slug, localAgents) {
138
+ const trimmed = slug.trim();
139
+ if (!trimmed)
140
+ return trimmed;
141
+ if (localAgents.some((agent) => agent.slug === trimmed))
142
+ return trimmed;
143
+ const candidate = localAgents.find((agent) => {
144
+ if (agent.remoteSlug === trimmed)
145
+ return true;
146
+ if (isCloudAgent(agent) && agent.slug === syncedCloudSlug({ ...agent, slug: trimmed })) {
147
+ return true;
148
+ }
149
+ if (isSelfHostedAgent(agent) &&
150
+ agent.slug === syncedSelfHostedSlug({ ...agent, slug: trimmed })) {
151
+ return true;
152
+ }
153
+ return false;
154
+ });
155
+ return candidate?.slug ?? trimmed;
156
+ }
157
+ export function getVirtualAgentWindow(items, input) {
158
+ const rowHeight = Math.max(1, Math.trunc(input.rowHeight));
159
+ const viewportHeight = Math.max(1, Math.trunc(input.viewportHeight));
160
+ const overscan = Math.max(0, Math.trunc(input.overscan ?? 4));
161
+ const totalHeight = items.length * rowHeight;
162
+ const visibleStart = Math.floor(Math.max(0, input.scrollTop) / rowHeight);
163
+ const visibleCount = Math.ceil(viewportHeight / rowHeight);
164
+ const startIndex = Math.max(0, visibleStart - overscan);
165
+ const endIndex = Math.min(items.length, visibleStart + visibleCount + overscan);
166
+ return {
167
+ startIndex,
168
+ endIndex,
169
+ items: items.slice(startIndex, endIndex),
170
+ beforeHeight: startIndex * rowHeight,
171
+ afterHeight: Math.max(0, totalHeight - endIndex * rowHeight),
172
+ totalHeight,
173
+ };
174
+ }
175
+ function resolveSelfHostedServer(agent) {
176
+ const nodeId = agent.nodeId?.trim() || undefined;
177
+ const serverName = agent.serverName?.trim() || undefined;
178
+ const serverId = agent.serverId?.trim() || undefined;
179
+ if (nodeId || serverName || serverId) {
180
+ const id = normalizeSlugPart(serverId ?? nodeId ?? serverName ?? "server");
181
+ return {
182
+ id,
183
+ label: agent.serverLabel ?? serverName ?? nodeId ?? serverId ?? id,
184
+ nodeId,
185
+ serverName,
186
+ status: agent.healthStatus,
187
+ remoteSlugPrefix: undefined,
188
+ };
189
+ }
190
+ const remote = agent.remoteSlug ?? agent.slug;
191
+ const parts = truthyStrings(remote.split(/[-_:/.]+/));
192
+ const prefixParts = parts.length >= 2 ? parts.slice(0, 2) : parts.slice(0, 1);
193
+ const remoteSlugPrefix = prefixParts.join("-");
194
+ const id = normalizeSlugPart(remoteSlugPrefix || remote || "server") || "server";
195
+ return {
196
+ id,
197
+ label: remoteSlugPrefix || id,
198
+ status: agent.healthStatus,
199
+ remoteSlugPrefix: remoteSlugPrefix || null,
200
+ };
201
+ }
202
+ function mergeServerStatus(current, next) {
203
+ if (current === "healthy" || next === "healthy")
204
+ return "healthy";
205
+ if (current === "degraded" || next === "degraded")
206
+ return "degraded";
207
+ return current ?? next;
208
+ }
209
+ function sortAgents(agents) {
210
+ return [...agents].sort((left, right) => {
211
+ const healthRank = healthScore(right.healthStatus) - healthScore(left.healthStatus);
212
+ if (healthRank !== 0)
213
+ return healthRank;
214
+ const ratingRank = (right.rating ?? -1) - (left.rating ?? -1);
215
+ if (ratingRank !== 0)
216
+ return ratingRank;
217
+ const leftName = left.displayName ?? left.slug;
218
+ const rightName = right.displayName ?? right.slug;
219
+ return leftName.localeCompare(rightName);
220
+ });
221
+ }
222
+ function healthScore(value) {
223
+ const normalized = value?.trim().toLowerCase();
224
+ if (normalized === "healthy")
225
+ return 3;
226
+ if (normalized === "degraded" || normalized === "limited")
227
+ return 2;
228
+ if (normalized === "unreachable" || normalized === "offline")
229
+ return 1;
230
+ return 0;
231
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./catalog.js";
2
+ export * from "./normalization.js";
3
+ export type * from "../types.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/headless/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,mBAAmB,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./catalog.js";
2
+ export * from "./normalization.js";
@@ -0,0 +1,12 @@
1
+ import type { McodaAgentCatalogEntry, McodaAgentManagedKind, McodaAgentSource } from "../types.js";
2
+ export declare function normalizeAgentCatalogEntry(raw: unknown, fallback: {
3
+ source: McodaAgentSource;
4
+ synced?: boolean;
5
+ managedKind?: McodaAgentManagedKind;
6
+ }): McodaAgentCatalogEntry;
7
+ export declare function normalizeAgentCatalogEntries(raw: unknown, fallback: {
8
+ source: McodaAgentSource;
9
+ synced?: boolean;
10
+ managedKind?: McodaAgentManagedKind;
11
+ }): McodaAgentCatalogEntry[];
12
+ //# sourceMappingURL=normalization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalization.d.ts","sourceRoot":"","sources":["../../src/headless/normalization.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAwBrB,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE;IACR,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,qBAAqB,CAAC;CACrC,GACA,sBAAsB,CA2GxB;AAED,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE;IACR,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,qBAAqB,CAAC;CACrC,GACA,sBAAsB,EAAE,CAO1B"}
@@ -0,0 +1,105 @@
1
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2
+ const stringValue = (value) => typeof value === "string" && value.trim() ? value : null;
3
+ const numberValue = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
4
+ const booleanValue = (value) => typeof value === "boolean" ? value : null;
5
+ const stringArrayValue = (value) => Array.isArray(value)
6
+ ? value
7
+ .map((item) => (typeof item === "string" ? item.trim() : ""))
8
+ .filter(Boolean)
9
+ : undefined;
10
+ const recordValue = (value) => isRecord(value) ? value : undefined;
11
+ export function normalizeAgentCatalogEntry(raw, fallback) {
12
+ const record = isRecord(raw) ? raw : {};
13
+ const config = recordValue(record.config);
14
+ const mswarmCloud = recordValue(config?.mswarmCloud);
15
+ const mswarmSelfHosted = recordValue(config?.mswarmSelfHosted);
16
+ const sync = recordValue(record.sync) ?? recordValue(mswarmSelfHosted?.sync);
17
+ const managedKind = fallback.managedKind ??
18
+ (mswarmCloud ? "cloud" : mswarmSelfHosted ? "self_hosted" : null);
19
+ const remoteSlug = stringValue(record.remoteSlug) ??
20
+ stringValue(record.remote_slug) ??
21
+ stringValue(mswarmCloud?.remoteSlug) ??
22
+ stringValue(mswarmSelfHosted?.remoteSlug);
23
+ const slug = stringValue(record.slug) ??
24
+ stringValue(record.agent_slug) ??
25
+ stringValue(mswarmSelfHosted?.agentSlug) ??
26
+ remoteSlug ??
27
+ "agent";
28
+ const defaultModel = stringValue(record.defaultModel) ??
29
+ stringValue(record.default_model) ??
30
+ stringValue(record.defaultModelId) ??
31
+ stringValue(record.model_id) ??
32
+ stringValue(mswarmCloud?.modelId) ??
33
+ stringValue(mswarmSelfHosted?.modelId);
34
+ const model = stringValue(record.model) ??
35
+ stringValue(record.modelId) ??
36
+ stringValue(record.model_id) ??
37
+ defaultModel;
38
+ const health = recordValue(record.health);
39
+ const healthStatus = stringValue(record.healthStatus) ??
40
+ stringValue(record.health_status) ??
41
+ stringValue(health?.status) ??
42
+ stringValue(record.status);
43
+ const nodeId = stringValue(record.nodeId) ??
44
+ stringValue(record.node_id) ??
45
+ stringValue(mswarmSelfHosted?.nodeId) ??
46
+ stringValue(sync?.node_id);
47
+ const serverName = stringValue(record.serverName) ??
48
+ stringValue(record.server_name) ??
49
+ stringValue(mswarmSelfHosted?.serverName) ??
50
+ stringValue(sync?.server_name);
51
+ return {
52
+ slug,
53
+ source: fallback.source,
54
+ synced: fallback.synced ?? fallback.source === "local_registry",
55
+ remoteSlug,
56
+ managedKind,
57
+ nodeId,
58
+ serverName,
59
+ serverId: stringValue(record.serverId) ??
60
+ stringValue(record.server_id) ??
61
+ stringValue(sync?.server_id),
62
+ serverLabel: stringValue(record.serverLabel) ??
63
+ stringValue(record.server_label) ??
64
+ serverName,
65
+ displayName: stringValue(record.displayName) ??
66
+ stringValue(record.display_name) ??
67
+ stringValue(mswarmCloud?.displayName) ??
68
+ stringValue(mswarmSelfHosted?.displayName),
69
+ provider: stringValue(record.provider) ??
70
+ stringValue(mswarmCloud?.provider) ??
71
+ stringValue(mswarmSelfHosted?.provider),
72
+ adapter: stringValue(record.adapter) ??
73
+ stringValue(mswarmSelfHosted?.adapter),
74
+ model,
75
+ defaultModel,
76
+ healthStatus,
77
+ supportsTools: booleanValue(record.supportsTools) ??
78
+ booleanValue(record.supports_tools),
79
+ rating: numberValue(record.rating),
80
+ reasoningRating: numberValue(record.reasoningRating) ??
81
+ numberValue(record.reasoning_rating),
82
+ maxComplexity: numberValue(record.maxComplexity) ??
83
+ numberValue(record.max_complexity),
84
+ costPerMillion: numberValue(record.costPerMillion) ??
85
+ numberValue(record.cost_per_million),
86
+ contextWindow: numberValue(record.contextWindow) ??
87
+ numberValue(record.context_window),
88
+ maxOutputTokens: numberValue(record.maxOutputTokens) ??
89
+ numberValue(record.max_output_tokens),
90
+ bestUsage: stringValue(record.bestUsage) ??
91
+ stringValue(record.best_usage),
92
+ capabilities: stringArrayValue(record.capabilities),
93
+ metadata: {
94
+ raw,
95
+ },
96
+ };
97
+ }
98
+ export function normalizeAgentCatalogEntries(raw, fallback) {
99
+ const values = Array.isArray(raw)
100
+ ? raw
101
+ : isRecord(raw) && Array.isArray(raw.agents)
102
+ ? raw.agents
103
+ : [];
104
+ return values.map((item) => normalizeAgentCatalogEntry(item, fallback));
105
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./types.js";
2
+ export * from "./defaultStages.js";
3
+ export * from "./client.js";
4
+ export * from "./headless/index.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from "./types.js";
2
+ export * from "./defaultStages.js";
3
+ export * from "./client.js";
4
+ export * from "./headless/index.js";