@sammorrowdrums/mcpi-ext 0.1.0 → 0.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 (170) hide show
  1. package/.github/workflows/ci.yml +1 -1
  2. package/README.md +109 -139
  3. package/docs/code-mode.md +38 -0
  4. package/docs/skills.md +57 -0
  5. package/docs/tool-cli.md +54 -0
  6. package/images/code-mode-histogram.png +0 -0
  7. package/images/skills-enabling-mcp-tools.png +0 -0
  8. package/images/tool-cli-grep.png +0 -0
  9. package/mise.toml +1 -13
  10. package/package.json +5 -7
  11. package/scripts/test-tool-cli-smoke.mjs +40 -9
  12. package/src/index.ts +24 -3
  13. package/src/tool-cli/index.ts +2 -2
  14. package/dist/code-mode/code-mode-integration.test.d.ts +0 -2
  15. package/dist/code-mode/code-mode-integration.test.d.ts.map +0 -1
  16. package/dist/code-mode/code-mode-integration.test.js +0 -116
  17. package/dist/code-mode/code-mode-integration.test.js.map +0 -1
  18. package/dist/code-mode/eligibility.d.ts +0 -10
  19. package/dist/code-mode/eligibility.d.ts.map +0 -1
  20. package/dist/code-mode/eligibility.js +0 -14
  21. package/dist/code-mode/eligibility.js.map +0 -1
  22. package/dist/code-mode/eligibility.test.d.ts +0 -2
  23. package/dist/code-mode/eligibility.test.d.ts.map +0 -1
  24. package/dist/code-mode/eligibility.test.js +0 -53
  25. package/dist/code-mode/eligibility.test.js.map +0 -1
  26. package/dist/code-mode/executor.d.ts +0 -35
  27. package/dist/code-mode/executor.d.ts.map +0 -1
  28. package/dist/code-mode/executor.js +0 -120
  29. package/dist/code-mode/executor.js.map +0 -1
  30. package/dist/code-mode/executor.test.d.ts +0 -2
  31. package/dist/code-mode/executor.test.d.ts.map +0 -1
  32. package/dist/code-mode/executor.test.js +0 -130
  33. package/dist/code-mode/executor.test.js.map +0 -1
  34. package/dist/code-mode/index.d.ts +0 -65
  35. package/dist/code-mode/index.d.ts.map +0 -1
  36. package/dist/code-mode/index.js +0 -175
  37. package/dist/code-mode/index.js.map +0 -1
  38. package/dist/code-mode/tools.d.ts +0 -45
  39. package/dist/code-mode/tools.d.ts.map +0 -1
  40. package/dist/code-mode/tools.js +0 -70
  41. package/dist/code-mode/tools.js.map +0 -1
  42. package/dist/code-mode/type-hints.d.ts +0 -20
  43. package/dist/code-mode/type-hints.d.ts.map +0 -1
  44. package/dist/code-mode/type-hints.js +0 -189
  45. package/dist/code-mode/type-hints.js.map +0 -1
  46. package/dist/code-mode/type-hints.test.d.ts +0 -2
  47. package/dist/code-mode/type-hints.test.d.ts.map +0 -1
  48. package/dist/code-mode/type-hints.test.js +0 -157
  49. package/dist/code-mode/type-hints.test.js.map +0 -1
  50. package/dist/docker-e2e.d.ts +0 -55
  51. package/dist/docker-e2e.d.ts.map +0 -1
  52. package/dist/docker-e2e.js +0 -235
  53. package/dist/docker-e2e.js.map +0 -1
  54. package/dist/docker-e2e.test.d.ts +0 -2
  55. package/dist/docker-e2e.test.d.ts.map +0 -1
  56. package/dist/docker-e2e.test.js +0 -176
  57. package/dist/docker-e2e.test.js.map +0 -1
  58. package/dist/index.d.ts +0 -3
  59. package/dist/index.d.ts.map +0 -1
  60. package/dist/index.js +0 -128
  61. package/dist/index.js.map +0 -1
  62. package/dist/index.test.d.ts +0 -2
  63. package/dist/index.test.d.ts.map +0 -1
  64. package/dist/index.test.js +0 -8
  65. package/dist/index.test.js.map +0 -1
  66. package/dist/mcp/client-manager.d.ts +0 -46
  67. package/dist/mcp/client-manager.d.ts.map +0 -1
  68. package/dist/mcp/client-manager.js +0 -148
  69. package/dist/mcp/client-manager.js.map +0 -1
  70. package/dist/mcp/client-manager.test.d.ts +0 -2
  71. package/dist/mcp/client-manager.test.d.ts.map +0 -1
  72. package/dist/mcp/client-manager.test.js +0 -204
  73. package/dist/mcp/client-manager.test.js.map +0 -1
  74. package/dist/mcp/config-loader.d.ts +0 -8
  75. package/dist/mcp/config-loader.d.ts.map +0 -1
  76. package/dist/mcp/config-loader.js +0 -43
  77. package/dist/mcp/config-loader.js.map +0 -1
  78. package/dist/mcp/config-loader.test.d.ts +0 -2
  79. package/dist/mcp/config-loader.test.d.ts.map +0 -1
  80. package/dist/mcp/config-loader.test.js +0 -93
  81. package/dist/mcp/config-loader.test.js.map +0 -1
  82. package/dist/mcp/config.d.ts +0 -46
  83. package/dist/mcp/config.d.ts.map +0 -1
  84. package/dist/mcp/config.js +0 -28
  85. package/dist/mcp/config.js.map +0 -1
  86. package/dist/mcp/index.d.ts +0 -5
  87. package/dist/mcp/index.d.ts.map +0 -1
  88. package/dist/mcp/index.js +0 -4
  89. package/dist/mcp/index.js.map +0 -1
  90. package/dist/skills/discover.d.ts +0 -10
  91. package/dist/skills/discover.d.ts.map +0 -1
  92. package/dist/skills/discover.js +0 -60
  93. package/dist/skills/discover.js.map +0 -1
  94. package/dist/skills/format.d.ts +0 -10
  95. package/dist/skills/format.d.ts.map +0 -1
  96. package/dist/skills/format.js +0 -38
  97. package/dist/skills/format.js.map +0 -1
  98. package/dist/skills/format.test.d.ts +0 -2
  99. package/dist/skills/format.test.d.ts.map +0 -1
  100. package/dist/skills/format.test.js +0 -63
  101. package/dist/skills/format.test.js.map +0 -1
  102. package/dist/skills/index.d.ts +0 -6
  103. package/dist/skills/index.d.ts.map +0 -1
  104. package/dist/skills/index.js +0 -6
  105. package/dist/skills/index.js.map +0 -1
  106. package/dist/skills/load-skill-tool.d.ts +0 -40
  107. package/dist/skills/load-skill-tool.d.ts.map +0 -1
  108. package/dist/skills/load-skill-tool.js +0 -104
  109. package/dist/skills/load-skill-tool.js.map +0 -1
  110. package/dist/skills/mcp-tool-proxy.d.ts +0 -11
  111. package/dist/skills/mcp-tool-proxy.d.ts.map +0 -1
  112. package/dist/skills/mcp-tool-proxy.js +0 -116
  113. package/dist/skills/mcp-tool-proxy.js.map +0 -1
  114. package/dist/skills/skill-integration.test.d.ts +0 -2
  115. package/dist/skills/skill-integration.test.d.ts.map +0 -1
  116. package/dist/skills/skill-integration.test.js +0 -119
  117. package/dist/skills/skill-integration.test.js.map +0 -1
  118. package/dist/skills/skill-registry.d.ts +0 -39
  119. package/dist/skills/skill-registry.d.ts.map +0 -1
  120. package/dist/skills/skill-registry.js +0 -48
  121. package/dist/skills/skill-registry.js.map +0 -1
  122. package/dist/skills/skill-registry.test.d.ts +0 -2
  123. package/dist/skills/skill-registry.test.d.ts.map +0 -1
  124. package/dist/skills/skill-registry.test.js +0 -67
  125. package/dist/skills/skill-registry.test.js.map +0 -1
  126. package/dist/test-servers/weather-server.d.ts +0 -12
  127. package/dist/test-servers/weather-server.d.ts.map +0 -1
  128. package/dist/test-servers/weather-server.js +0 -139
  129. package/dist/test-servers/weather-server.js.map +0 -1
  130. package/dist/test-servers/weather-stdio.d.ts +0 -2
  131. package/dist/test-servers/weather-stdio.d.ts.map +0 -1
  132. package/dist/test-servers/weather-stdio.js +0 -11
  133. package/dist/test-servers/weather-stdio.js.map +0 -1
  134. package/dist/tool-cli/cli.d.ts +0 -3
  135. package/dist/tool-cli/cli.d.ts.map +0 -1
  136. package/dist/tool-cli/cli.js +0 -179
  137. package/dist/tool-cli/cli.js.map +0 -1
  138. package/dist/tool-cli/constants.d.ts +0 -7
  139. package/dist/tool-cli/constants.d.ts.map +0 -1
  140. package/dist/tool-cli/constants.js +0 -15
  141. package/dist/tool-cli/constants.js.map +0 -1
  142. package/dist/tool-cli/format.d.ts +0 -8
  143. package/dist/tool-cli/format.d.ts.map +0 -1
  144. package/dist/tool-cli/format.js +0 -57
  145. package/dist/tool-cli/format.js.map +0 -1
  146. package/dist/tool-cli/format.test.d.ts +0 -2
  147. package/dist/tool-cli/format.test.d.ts.map +0 -1
  148. package/dist/tool-cli/format.test.js +0 -30
  149. package/dist/tool-cli/format.test.js.map +0 -1
  150. package/dist/tool-cli/index.d.ts +0 -4
  151. package/dist/tool-cli/index.d.ts.map +0 -1
  152. package/dist/tool-cli/index.js +0 -4
  153. package/dist/tool-cli/index.js.map +0 -1
  154. package/dist/tool-cli/rpc-client.d.ts +0 -6
  155. package/dist/tool-cli/rpc-client.d.ts.map +0 -1
  156. package/dist/tool-cli/rpc-client.js +0 -25
  157. package/dist/tool-cli/rpc-client.js.map +0 -1
  158. package/dist/tool-cli/rpc-server.d.ts +0 -48
  159. package/dist/tool-cli/rpc-server.d.ts.map +0 -1
  160. package/dist/tool-cli/rpc-server.js +0 -220
  161. package/dist/tool-cli/rpc-server.js.map +0 -1
  162. package/dist/tool-cli/rpc-server.test.d.ts +0 -2
  163. package/dist/tool-cli/rpc-server.test.d.ts.map +0 -1
  164. package/dist/tool-cli/rpc-server.test.js +0 -154
  165. package/dist/tool-cli/rpc-server.test.js.map +0 -1
  166. package/src/tool-cli/cli.ts +0 -232
  167. package/src/tool-cli/constants.ts +0 -15
  168. package/src/tool-cli/rpc-client.ts +0 -39
  169. package/src/tool-cli/rpc-server.test.ts +0 -193
  170. package/src/tool-cli/rpc-server.ts +0 -287
@@ -1,189 +0,0 @@
1
- /**
2
- * Convert a JSON Schema to a TypeScript type string.
3
- *
4
- * Handles objects, arrays, primitives, enums, anyOf/oneOf/allOf, $ref,
5
- * and circular references (depth guard at 20).
6
- */
7
- export function jsonSchemaToTypeString(schema, definitions, depth = 0, seen = new Set()) {
8
- if (depth > 20)
9
- return "unknown";
10
- if (seen.has(schema))
11
- return "unknown";
12
- seen.add(schema);
13
- // Handle $ref
14
- if (typeof schema.$ref === "string") {
15
- const refPath = schema.$ref;
16
- const refName = refPath.replace(/^#\/(definitions|components\/schemas|\\$defs)\//, "");
17
- const resolved = definitions?.[refName];
18
- if (resolved) {
19
- return jsonSchemaToTypeString(resolved, definitions, depth + 1, seen);
20
- }
21
- return "unknown";
22
- }
23
- // Handle enum
24
- if (Array.isArray(schema.enum)) {
25
- return schema.enum.map((v) => JSON.stringify(v)).join(" | ");
26
- }
27
- // Handle const
28
- if ("const" in schema) {
29
- return JSON.stringify(schema.const);
30
- }
31
- // Handle anyOf / oneOf
32
- const unionKey = schema.anyOf ? "anyOf" : schema.oneOf ? "oneOf" : null;
33
- if (unionKey && Array.isArray(schema[unionKey])) {
34
- const variants = schema[unionKey].map((s) => jsonSchemaToTypeString(s, definitions, depth + 1, seen));
35
- return variants.join(" | ");
36
- }
37
- // Handle allOf
38
- if (Array.isArray(schema.allOf)) {
39
- const parts = schema.allOf.map((s) => jsonSchemaToTypeString(s, definitions, depth + 1, seen));
40
- return parts.join(" & ");
41
- }
42
- const type = schema.type;
43
- // Handle type arrays (e.g. ["string", "null"])
44
- if (Array.isArray(type)) {
45
- const types = type.map((t) => primitiveToTs(t));
46
- return types.join(" | ");
47
- }
48
- switch (type) {
49
- case "object":
50
- return objectToTs(schema, definitions, depth, seen);
51
- case "array":
52
- return arrayToTs(schema, definitions, depth, seen);
53
- case "string":
54
- case "number":
55
- case "integer":
56
- case "boolean":
57
- case "null":
58
- return primitiveToTs(type);
59
- default:
60
- // No type specified — try to infer from properties
61
- if (schema.properties) {
62
- return objectToTs(schema, definitions, depth, seen);
63
- }
64
- return "unknown";
65
- }
66
- }
67
- function primitiveToTs(type) {
68
- switch (type) {
69
- case "string":
70
- return "string";
71
- case "number":
72
- case "integer":
73
- return "number";
74
- case "boolean":
75
- return "boolean";
76
- case "null":
77
- return "null";
78
- default:
79
- return "unknown";
80
- }
81
- }
82
- function objectToTs(schema, definitions, depth, seen) {
83
- const properties = schema.properties;
84
- if (!properties || Object.keys(properties).length === 0) {
85
- return "Record<string, unknown>";
86
- }
87
- const required = new Set(Array.isArray(schema.required) ? schema.required : []);
88
- const lines = [];
89
- for (const [key, propSchema] of Object.entries(properties)) {
90
- const desc = propSchema.description;
91
- if (desc) {
92
- lines.push(` /** ${desc} */`);
93
- }
94
- const optional = required.has(key) ? "" : "?";
95
- const typeStr = jsonSchemaToTypeString(propSchema, definitions, depth + 1, seen);
96
- lines.push(` ${safeName(key)}${optional}: ${typeStr};`);
97
- }
98
- return `{\n${lines.join("\n")}\n}`;
99
- }
100
- function arrayToTs(schema, definitions, depth, seen) {
101
- const items = schema.items;
102
- if (!items)
103
- return "unknown[]";
104
- // Tuple form
105
- if (Array.isArray(items)) {
106
- const tupleTypes = items.map((s) => jsonSchemaToTypeString(s, definitions, depth + 1, seen));
107
- return `[${tupleTypes.join(", ")}]`;
108
- }
109
- const itemType = jsonSchemaToTypeString(items, definitions, depth + 1, seen);
110
- return `${itemType}[]`;
111
- }
112
- /** Ensure property name is a valid JS identifier, quote otherwise. */
113
- function safeName(name) {
114
- return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
115
- }
116
- /** Sanitize a tool name to be a valid JS identifier. */
117
- export function sanitizeToolName(name) {
118
- return name.replace(/[^a-zA-Z0-9_$]/g, "_");
119
- }
120
- /**
121
- * Generate TypeScript type declarations for a set of MCP tools.
122
- *
123
- * Produces a `declare const codemode: { ... }` block with type-safe
124
- * method signatures the model can use when writing code.
125
- */
126
- export function generateTypeHints(tools) {
127
- if (tools.length === 0)
128
- return "";
129
- const methods = [];
130
- for (const tool of tools) {
131
- const safeName = sanitizeToolName(tool.name);
132
- const inputSchema = tool.inputSchema;
133
- const outputSchema = tool.outputSchema;
134
- const definitions = (inputSchema.$defs ??
135
- inputSchema.definitions ??
136
- outputSchema?.$defs ??
137
- outputSchema?.definitions);
138
- // Build input type
139
- const inputType = generateInputType(safeName, inputSchema, definitions);
140
- // Build output type
141
- const outputType = outputSchema ? jsonSchemaToTypeString(outputSchema, definitions) : "unknown";
142
- // Build JSDoc
143
- const jsdoc = buildJsDoc(tool, inputSchema);
144
- methods.push(`${jsdoc} ${safeName}: (input: ${inputType}) => Promise<${outputType}>;`);
145
- }
146
- const toolListType = tools.map((t) => `"${escapeStr(t.name)}"`).join(" | ");
147
- return [
148
- "// Code mode type hints — auto-generated from MCP tool schemas",
149
- "// Available tools are accessed via the `codemode` namespace",
150
- "",
151
- `declare const codemode: {`,
152
- ` /** List all available code mode tool names. */`,
153
- ` listTools: () => Promise<(${toolListType})[]>;`,
154
- ` /** Get full type information for specific tools. */`,
155
- ` describeTools: (names: string[]) => Promise<string>;`,
156
- ...methods.map((m) => m),
157
- `};`,
158
- ].join("\n");
159
- }
160
- function generateInputType(_toolSafeName, inputSchema, definitions) {
161
- const properties = inputSchema.properties;
162
- if (!properties || Object.keys(properties).length === 0) {
163
- return "Record<string, never>";
164
- }
165
- // Always inline the type — avoids emitting unreferenced named type aliases
166
- const typeStr = jsonSchemaToTypeString(inputSchema, definitions);
167
- return typeStr;
168
- }
169
- function buildJsDoc(tool, inputSchema) {
170
- const lines = [" /**"];
171
- if (tool.description) {
172
- lines.push(` * ${tool.description}`);
173
- }
174
- const properties = inputSchema.properties;
175
- if (properties) {
176
- for (const [key, propSchema] of Object.entries(properties)) {
177
- const desc = propSchema.description;
178
- if (desc) {
179
- lines.push(` * @param input.${key} - ${desc}`);
180
- }
181
- }
182
- }
183
- lines.push(" */");
184
- return lines.join("\n") + "\n";
185
- }
186
- function escapeStr(s) {
187
- return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, " ");
188
- }
189
- //# sourceMappingURL=type-hints.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"type-hints.js","sourceRoot":"","sources":["../../src/code-mode/type-hints.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=type-hints.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"type-hints.test.d.ts","sourceRoot":"","sources":["../../src/code-mode/type-hints.test.ts"],"names":[],"mappings":""}
@@ -1,157 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { generateTypeHints, jsonSchemaToTypeString, sanitizeToolName } from "./type-hints.js";
3
- describe("jsonSchemaToTypeString", () => {
4
- it("converts string type", () => {
5
- expect(jsonSchemaToTypeString({ type: "string" })).toBe("string");
6
- });
7
- it("converts number type", () => {
8
- expect(jsonSchemaToTypeString({ type: "number" })).toBe("number");
9
- });
10
- it("converts integer type", () => {
11
- expect(jsonSchemaToTypeString({ type: "integer" })).toBe("number");
12
- });
13
- it("converts boolean type", () => {
14
- expect(jsonSchemaToTypeString({ type: "boolean" })).toBe("boolean");
15
- });
16
- it("converts null type", () => {
17
- expect(jsonSchemaToTypeString({ type: "null" })).toBe("null");
18
- });
19
- it("converts type array", () => {
20
- expect(jsonSchemaToTypeString({ type: ["string", "null"] })).toBe("string | null");
21
- });
22
- it("converts enum to union", () => {
23
- expect(jsonSchemaToTypeString({ enum: ["a", "b", "c"] })).toBe('"a" | "b" | "c"');
24
- });
25
- it("converts const", () => {
26
- expect(jsonSchemaToTypeString({ const: "fixed" })).toBe('"fixed"');
27
- });
28
- it("converts simple object", () => {
29
- const result = jsonSchemaToTypeString({
30
- type: "object",
31
- properties: {
32
- name: { type: "string" },
33
- age: { type: "number" },
34
- },
35
- required: ["name"],
36
- });
37
- expect(result).toContain("name: string;");
38
- expect(result).toContain("age?: number;");
39
- });
40
- it("converts empty object to Record", () => {
41
- expect(jsonSchemaToTypeString({ type: "object" })).toBe("Record<string, unknown>");
42
- });
43
- it("converts array with items", () => {
44
- expect(jsonSchemaToTypeString({ type: "array", items: { type: "string" } })).toBe("string[]");
45
- });
46
- it("converts array without items", () => {
47
- expect(jsonSchemaToTypeString({ type: "array" })).toBe("unknown[]");
48
- });
49
- it("handles anyOf", () => {
50
- const result = jsonSchemaToTypeString({
51
- anyOf: [{ type: "string" }, { type: "number" }],
52
- });
53
- expect(result).toBe("string | number");
54
- });
55
- it("handles oneOf", () => {
56
- const result = jsonSchemaToTypeString({
57
- oneOf: [{ type: "boolean" }, { type: "null" }],
58
- });
59
- expect(result).toBe("boolean | null");
60
- });
61
- it("handles allOf", () => {
62
- const result = jsonSchemaToTypeString({
63
- allOf: [
64
- { type: "object", properties: { a: { type: "string" } }, required: ["a"] },
65
- { type: "object", properties: { b: { type: "number" } }, required: ["b"] },
66
- ],
67
- });
68
- expect(result).toContain("a: string;");
69
- expect(result).toContain("b: number;");
70
- expect(result).toContain("&");
71
- });
72
- it("resolves $ref", () => {
73
- const result = jsonSchemaToTypeString({ $ref: "#/definitions/Foo" }, { Foo: { type: "string" } });
74
- expect(result).toBe("string");
75
- });
76
- it("handles unknown $ref gracefully", () => {
77
- expect(jsonSchemaToTypeString({ $ref: "#/definitions/Missing" }, {})).toBe("unknown");
78
- });
79
- it("guards against deep recursion", () => {
80
- // Create a deeply nested schema
81
- let schema = { type: "string" };
82
- for (let i = 0; i < 25; i++) {
83
- schema = { type: "object", properties: { nested: schema }, required: ["nested"] };
84
- }
85
- const result = jsonSchemaToTypeString(schema);
86
- expect(result).toContain("unknown"); // Should hit depth guard
87
- });
88
- it("includes description as JSDoc in object properties", () => {
89
- const result = jsonSchemaToTypeString({
90
- type: "object",
91
- properties: {
92
- query: { type: "string", description: "Search term" },
93
- },
94
- required: ["query"],
95
- });
96
- expect(result).toContain("/** Search term */");
97
- });
98
- });
99
- describe("sanitizeToolName", () => {
100
- it("replaces hyphens with underscores", () => {
101
- expect(sanitizeToolName("list-issues")).toBe("list_issues");
102
- });
103
- it("replaces dots with underscores", () => {
104
- expect(sanitizeToolName("github.search")).toBe("github_search");
105
- });
106
- it("keeps valid identifiers unchanged", () => {
107
- expect(sanitizeToolName("searchDocs")).toBe("searchDocs");
108
- });
109
- });
110
- describe("generateTypeHints", () => {
111
- it("returns empty string for no tools", () => {
112
- expect(generateTypeHints([])).toBe("");
113
- });
114
- it("generates declaration for a simple tool", () => {
115
- const tools = [
116
- {
117
- name: "search_docs",
118
- description: "Search documentation",
119
- inputSchema: {
120
- type: "object",
121
- properties: {
122
- query: { type: "string", description: "Search term" },
123
- },
124
- required: ["query"],
125
- },
126
- outputSchema: {
127
- type: "object",
128
- properties: {
129
- results: { type: "array", items: { type: "string" } },
130
- },
131
- required: ["results"],
132
- },
133
- serverName: "docs",
134
- },
135
- ];
136
- const result = generateTypeHints(tools);
137
- expect(result).toContain("declare const codemode");
138
- expect(result).toContain("search_docs:");
139
- expect(result).toContain("Promise<");
140
- expect(result).toContain("listTools");
141
- expect(result).toContain("describeTools");
142
- });
143
- it("sanitizes tool names with special characters", () => {
144
- const tools = [
145
- {
146
- name: "github.list-repos",
147
- description: "List repos",
148
- inputSchema: { type: "object", properties: {} },
149
- outputSchema: { type: "object", properties: {} },
150
- serverName: "github",
151
- },
152
- ];
153
- const result = generateTypeHints(tools);
154
- expect(result).toContain("github_list_repos:");
155
- });
156
- });
157
- //# sourceMappingURL=type-hints.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"type-hints.test.js","sourceRoot":"","sources":["../../src/code-mode/type-hints.test.ts"],"names":[],"mappings":"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"}
@@ -1,55 +0,0 @@
1
- import type { AgentToolResult, AgentToolUpdateCallback, ExtensionContext } from "@sammorrowdrums/mcpi";
2
- import { Type, type Static } from "typebox";
3
- declare const DockerE2EParams: Type.TObject<{
4
- task: Type.TString;
5
- token: Type.TString;
6
- model: Type.TOptional<Type.TString>;
7
- timeout: Type.TOptional<Type.TNumber>;
8
- }>;
9
- type DockerE2EInput = Static<typeof DockerE2EParams>;
10
- interface RunLogEntry {
11
- type: string;
12
- timestamp: number;
13
- raw: string;
14
- }
15
- export interface DockerE2EDetails {
16
- exitCode: number | null;
17
- log: RunLogEntry[];
18
- duration: number;
19
- model?: string;
20
- usage?: {
21
- input: number;
22
- output: number;
23
- cacheRead: number;
24
- cacheWrite: number;
25
- cost: number;
26
- turns: number;
27
- };
28
- }
29
- export declare function parseJsonlLine(line: string): RunLogEntry | null;
30
- export declare function extractAssistantText(log: RunLogEntry[]): string;
31
- export declare function extractUsage(log: RunLogEntry[]): {
32
- input: number;
33
- output: number;
34
- cacheRead: number;
35
- cacheWrite: number;
36
- cost: number;
37
- turns: number;
38
- };
39
- export declare function extractModel(log: RunLogEntry[]): string | undefined;
40
- export declare function buildDockerArgs(image: string, params: DockerE2EInput): string[];
41
- export declare const dockerE2ETool: {
42
- name: string;
43
- label: string;
44
- description: string;
45
- promptSnippet: string;
46
- parameters: Type.TObject<{
47
- task: Type.TString;
48
- token: Type.TString;
49
- model: Type.TOptional<Type.TString>;
50
- timeout: Type.TOptional<Type.TNumber>;
51
- }>;
52
- execute(_toolCallId: string, params: DockerE2EInput, signal: AbortSignal | undefined, onUpdate: AgentToolUpdateCallback<DockerE2EDetails> | undefined, _ctx: ExtensionContext): Promise<AgentToolResult<DockerE2EDetails>>;
53
- };
54
- export {};
55
- //# sourceMappingURL=docker-e2e.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"docker-e2e.d.ts","sourceRoot":"","sources":["../src/docker-e2e.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,uBAAuB,EACvB,gBAAgB,EACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,IAAI,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAI5C,QAAA,MAAM,eAAe;;;;;EAenB,CAAC;AAEH,KAAK,cAAc,GAAG,MAAM,CAAC,OAAO,eAAe,CAAC,CAAC;AAErD,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,EAAE,WAAW,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAS/D;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,MAAM,CAgB/D;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,EAAE;;;;;;;EAsB9C;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,MAAM,GAAG,SAAS,CAWnE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,EAAE,CAS/E;AAED,eAAO,MAAM,aAAa;;;;;;;;;;;yBAST,MAAM,UACX,cAAc,UACd,WAAW,GAAG,SAAS,YACrB,uBAAuB,CAAC,gBAAgB,CAAC,GAAG,SAAS,QACzD,gBAAgB,GACrB,OAAO,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC;CAuI9C,CAAC"}
@@ -1,235 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- import { Type } from "typebox";
3
- const DOCKER_IMAGE = "mcpi-ext-e2e";
4
- const DockerE2EParams = Type.Object({
5
- task: Type.String({ description: "The task/prompt to run inside the sandbox" }),
6
- token: Type.String({
7
- description: "GitHub token for Copilot model access",
8
- }),
9
- model: Type.Optional(Type.String({
10
- description: "Model to use (e.g. claude-sonnet-4-5). Defaults to the provider default.",
11
- })),
12
- timeout: Type.Optional(Type.Number({
13
- description: "Timeout in seconds. Defaults to 300 (5 minutes).",
14
- })),
15
- });
16
- export function parseJsonlLine(line) {
17
- const trimmed = line.trim();
18
- if (!trimmed)
19
- return null;
20
- try {
21
- const parsed = JSON.parse(trimmed);
22
- return { type: parsed.type ?? "unknown", timestamp: Date.now(), raw: trimmed };
23
- }
24
- catch {
25
- return { type: "raw", timestamp: Date.now(), raw: trimmed };
26
- }
27
- }
28
- export function extractAssistantText(log) {
29
- const parts = [];
30
- for (const entry of log) {
31
- if (entry.type !== "message_end")
32
- continue;
33
- try {
34
- const event = JSON.parse(entry.raw);
35
- const msg = event.message;
36
- if (msg?.role !== "assistant")
37
- continue;
38
- for (const part of msg.content ?? []) {
39
- if (part.type === "text")
40
- parts.push(part.text);
41
- }
42
- }
43
- catch {
44
- // skip malformed
45
- }
46
- }
47
- return parts.join("\n");
48
- }
49
- export function extractUsage(log) {
50
- const usage = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 };
51
- for (const entry of log) {
52
- if (entry.type !== "message_end")
53
- continue;
54
- try {
55
- const event = JSON.parse(entry.raw);
56
- const msg = event.message;
57
- if (msg?.role !== "assistant")
58
- continue;
59
- usage.turns++;
60
- const u = msg.usage;
61
- if (u) {
62
- usage.input += u.input ?? 0;
63
- usage.output += u.output ?? 0;
64
- usage.cacheRead += u.cacheRead ?? 0;
65
- usage.cacheWrite += u.cacheWrite ?? 0;
66
- usage.cost += u.cost?.total ?? 0;
67
- }
68
- }
69
- catch {
70
- // skip
71
- }
72
- }
73
- return usage;
74
- }
75
- export function extractModel(log) {
76
- for (const entry of log) {
77
- if (entry.type !== "message_end")
78
- continue;
79
- try {
80
- const event = JSON.parse(entry.raw);
81
- if (event.message?.model)
82
- return event.message.model;
83
- }
84
- catch {
85
- // skip
86
- }
87
- }
88
- return undefined;
89
- }
90
- export function buildDockerArgs(image, params) {
91
- const args = ["run", "--rm", "-e", `GITHUB_TOKEN=${params.token}`];
92
- if (params.model) {
93
- args.push("-e", `PI_MODEL=${params.model}`);
94
- }
95
- args.push(image, params.task);
96
- return args;
97
- }
98
- export const dockerE2ETool = {
99
- name: "docker_e2e",
100
- label: "Docker E2E",
101
- description: "Run a task end-to-end inside an isolated Docker container with pi and this project's extensions. Returns the full run log for evaluation.",
102
- promptSnippet: "Run an isolated e2e task in Docker. Requires a GitHub token and task prompt.",
103
- parameters: DockerE2EParams,
104
- async execute(_toolCallId, params, signal, onUpdate, _ctx) {
105
- const startTime = Date.now();
106
- const timeoutMs = (params.timeout ?? 300) * 1000;
107
- const log = [];
108
- let lastAssistantText = "";
109
- const dockerArgs = buildDockerArgs(DOCKER_IMAGE, params);
110
- const exitCode = await new Promise((resolve) => {
111
- const proc = spawn("docker", dockerArgs, {
112
- stdio: ["ignore", "pipe", "pipe"],
113
- });
114
- let buffer = "";
115
- let timedOut = false;
116
- let timeoutHandle;
117
- if (timeoutMs > 0) {
118
- timeoutHandle = setTimeout(() => {
119
- timedOut = true;
120
- proc.kill("SIGTERM");
121
- setTimeout(() => {
122
- if (!proc.killed)
123
- proc.kill("SIGKILL");
124
- }, 5000);
125
- }, timeoutMs);
126
- }
127
- const processLine = (line) => {
128
- const entry = parseJsonlLine(line);
129
- if (!entry)
130
- return;
131
- log.push(entry);
132
- if (entry.type === "message_end") {
133
- const text = extractAssistantText(log);
134
- if (text)
135
- lastAssistantText = text;
136
- }
137
- onUpdate?.({
138
- content: [
139
- {
140
- type: "text",
141
- text: lastAssistantText || `(running… ${log.length} events)`,
142
- },
143
- ],
144
- details: {
145
- exitCode: null,
146
- log,
147
- duration: Date.now() - startTime,
148
- model: extractModel(log),
149
- usage: extractUsage(log),
150
- },
151
- });
152
- };
153
- proc.stdout.on("data", (data) => {
154
- buffer += data.toString();
155
- const lines = buffer.split("\n");
156
- buffer = lines.pop() ?? "";
157
- for (const line of lines)
158
- processLine(line);
159
- });
160
- proc.stderr.on("data", (data) => {
161
- const text = data.toString().trim();
162
- if (text) {
163
- log.push({ type: "stderr", timestamp: Date.now(), raw: text });
164
- }
165
- });
166
- proc.on("close", (code) => {
167
- if (timeoutHandle)
168
- clearTimeout(timeoutHandle);
169
- if (buffer.trim())
170
- processLine(buffer);
171
- if (timedOut) {
172
- log.push({
173
- type: "timeout",
174
- timestamp: Date.now(),
175
- raw: `Timed out after ${params.timeout ?? 300}s`,
176
- });
177
- }
178
- resolve(timedOut ? null : (code ?? 1));
179
- });
180
- proc.on("error", (err) => {
181
- if (timeoutHandle)
182
- clearTimeout(timeoutHandle);
183
- log.push({
184
- type: "error",
185
- timestamp: Date.now(),
186
- raw: err.message,
187
- });
188
- resolve(null);
189
- });
190
- if (signal) {
191
- const onAbort = () => {
192
- proc.kill("SIGTERM");
193
- setTimeout(() => {
194
- if (!proc.killed)
195
- proc.kill("SIGKILL");
196
- }, 5000);
197
- };
198
- if (signal.aborted)
199
- onAbort();
200
- else
201
- signal.addEventListener("abort", onAbort, { once: true });
202
- }
203
- });
204
- const duration = Date.now() - startTime;
205
- const assistantText = extractAssistantText(log);
206
- const usage = extractUsage(log);
207
- const model = extractModel(log);
208
- const fullLog = log.map((e) => e.raw).join("\n");
209
- const summary = [
210
- `## Docker E2E Run Complete`,
211
- ``,
212
- `**Exit code:** ${exitCode ?? "killed"}`,
213
- `**Duration:** ${(duration / 1000).toFixed(1)}s`,
214
- model ? `**Model:** ${model}` : null,
215
- usage.turns > 0
216
- ? `**Usage:** ${usage.turns} turns, ↑${usage.input} ↓${usage.output} tokens, $${usage.cost.toFixed(4)}`
217
- : null,
218
- ``,
219
- `### Output`,
220
- assistantText || "(no assistant output)",
221
- ``,
222
- `### Full Log (${log.length} events)`,
223
- "```",
224
- fullLog,
225
- "```",
226
- ]
227
- .filter((l) => l !== null)
228
- .join("\n");
229
- return {
230
- content: [{ type: "text", text: summary }],
231
- details: { exitCode, log, duration, model, usage },
232
- };
233
- },
234
- };
235
- //# sourceMappingURL=docker-e2e.js.map