localant 1.0.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 (218) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +290 -0
  3. package/SECURITY.md +87 -0
  4. package/examples/skills/hello-world/CHANGELOG.md +4 -0
  5. package/examples/skills/hello-world/LICENSE +1 -0
  6. package/examples/skills/hello-world/README.md +20 -0
  7. package/examples/skills/hello-world/examples/example.json +1 -0
  8. package/examples/skills/hello-world/package.json +9 -0
  9. package/examples/skills/hello-world/skill.json +32 -0
  10. package/examples/skills/hello-world/src/index.ts +19 -0
  11. package/examples/skills/hello-world/tests/index.test.ts +19 -0
  12. package/package.json +63 -0
  13. package/packages/cli/dist/bin.d.ts +3 -0
  14. package/packages/cli/dist/bin.d.ts.map +1 -0
  15. package/packages/cli/dist/bin.js +261 -0
  16. package/packages/cli/dist/bin.js.map +1 -0
  17. package/packages/cli/dist/doctor.d.ts +3 -0
  18. package/packages/cli/dist/doctor.d.ts.map +1 -0
  19. package/packages/cli/dist/doctor.js +35 -0
  20. package/packages/cli/dist/doctor.js.map +1 -0
  21. package/packages/cli/dist/index.d.ts +3 -0
  22. package/packages/cli/dist/index.d.ts.map +1 -0
  23. package/packages/cli/dist/index.js +3 -0
  24. package/packages/cli/dist/index.js.map +1 -0
  25. package/packages/cli/dist/runtime.d.ts +11 -0
  26. package/packages/cli/dist/runtime.d.ts.map +1 -0
  27. package/packages/cli/dist/runtime.js +82 -0
  28. package/packages/cli/dist/runtime.js.map +1 -0
  29. package/packages/cli/dist/util.d.ts +18 -0
  30. package/packages/cli/dist/util.d.ts.map +1 -0
  31. package/packages/cli/dist/util.js +47 -0
  32. package/packages/cli/dist/util.js.map +1 -0
  33. package/packages/cli/package.json +19 -0
  34. package/packages/dashboard/dist/index.d.ts +10 -0
  35. package/packages/dashboard/dist/index.d.ts.map +1 -0
  36. package/packages/dashboard/dist/index.js +178 -0
  37. package/packages/dashboard/dist/index.js.map +1 -0
  38. package/packages/dashboard/package.json +10 -0
  39. package/packages/gateway/dist/gateway.d.ts +85 -0
  40. package/packages/gateway/dist/gateway.d.ts.map +1 -0
  41. package/packages/gateway/dist/gateway.js +234 -0
  42. package/packages/gateway/dist/gateway.js.map +1 -0
  43. package/packages/gateway/dist/index.d.ts +13 -0
  44. package/packages/gateway/dist/index.d.ts.map +1 -0
  45. package/packages/gateway/dist/index.js +16 -0
  46. package/packages/gateway/dist/index.js.map +1 -0
  47. package/packages/gateway/dist/managers/coding-agent-manager.d.ts +71 -0
  48. package/packages/gateway/dist/managers/coding-agent-manager.d.ts.map +1 -0
  49. package/packages/gateway/dist/managers/coding-agent-manager.js +179 -0
  50. package/packages/gateway/dist/managers/coding-agent-manager.js.map +1 -0
  51. package/packages/gateway/dist/managers/fs-manager.d.ts +63 -0
  52. package/packages/gateway/dist/managers/fs-manager.d.ts.map +1 -0
  53. package/packages/gateway/dist/managers/fs-manager.js +229 -0
  54. package/packages/gateway/dist/managers/fs-manager.js.map +1 -0
  55. package/packages/gateway/dist/managers/git-manager.d.ts +21 -0
  56. package/packages/gateway/dist/managers/git-manager.d.ts.map +1 -0
  57. package/packages/gateway/dist/managers/git-manager.js +67 -0
  58. package/packages/gateway/dist/managers/git-manager.js.map +1 -0
  59. package/packages/gateway/dist/managers/mcp-bridge.d.ts +26 -0
  60. package/packages/gateway/dist/managers/mcp-bridge.d.ts.map +1 -0
  61. package/packages/gateway/dist/managers/mcp-bridge.js +92 -0
  62. package/packages/gateway/dist/managers/mcp-bridge.js.map +1 -0
  63. package/packages/gateway/dist/managers/project-registry.d.ts +17 -0
  64. package/packages/gateway/dist/managers/project-registry.d.ts.map +1 -0
  65. package/packages/gateway/dist/managers/project-registry.js +90 -0
  66. package/packages/gateway/dist/managers/project-registry.js.map +1 -0
  67. package/packages/gateway/dist/managers/shell-manager.d.ts +48 -0
  68. package/packages/gateway/dist/managers/shell-manager.d.ts.map +1 -0
  69. package/packages/gateway/dist/managers/shell-manager.js +132 -0
  70. package/packages/gateway/dist/managers/shell-manager.js.map +1 -0
  71. package/packages/gateway/dist/managers/skill-runtime.d.ts +37 -0
  72. package/packages/gateway/dist/managers/skill-runtime.d.ts.map +1 -0
  73. package/packages/gateway/dist/managers/skill-runtime.js +310 -0
  74. package/packages/gateway/dist/managers/skill-runtime.js.map +1 -0
  75. package/packages/gateway/dist/managers/tunnel-manager.d.ts +23 -0
  76. package/packages/gateway/dist/managers/tunnel-manager.d.ts.map +1 -0
  77. package/packages/gateway/dist/managers/tunnel-manager.js +106 -0
  78. package/packages/gateway/dist/managers/tunnel-manager.js.map +1 -0
  79. package/packages/gateway/dist/registry.d.ts +28 -0
  80. package/packages/gateway/dist/registry.d.ts.map +1 -0
  81. package/packages/gateway/dist/registry.js +20 -0
  82. package/packages/gateway/dist/registry.js.map +1 -0
  83. package/packages/gateway/dist/security/command-guard.d.ts +35 -0
  84. package/packages/gateway/dist/security/command-guard.d.ts.map +1 -0
  85. package/packages/gateway/dist/security/command-guard.js +105 -0
  86. package/packages/gateway/dist/security/command-guard.js.map +1 -0
  87. package/packages/gateway/dist/security/path-guard.d.ts +31 -0
  88. package/packages/gateway/dist/security/path-guard.d.ts.map +1 -0
  89. package/packages/gateway/dist/security/path-guard.js +101 -0
  90. package/packages/gateway/dist/security/path-guard.js.map +1 -0
  91. package/packages/gateway/dist/skill-runner.d.ts +2 -0
  92. package/packages/gateway/dist/skill-runner.d.ts.map +1 -0
  93. package/packages/gateway/dist/skill-runner.js +38 -0
  94. package/packages/gateway/dist/skill-runner.js.map +1 -0
  95. package/packages/gateway/dist/stores/approval-store.d.ts +34 -0
  96. package/packages/gateway/dist/stores/approval-store.d.ts.map +1 -0
  97. package/packages/gateway/dist/stores/approval-store.js +108 -0
  98. package/packages/gateway/dist/stores/approval-store.js.map +1 -0
  99. package/packages/gateway/dist/stores/audit-log.d.ts +23 -0
  100. package/packages/gateway/dist/stores/audit-log.d.ts.map +1 -0
  101. package/packages/gateway/dist/stores/audit-log.js +70 -0
  102. package/packages/gateway/dist/stores/audit-log.js.map +1 -0
  103. package/packages/gateway/dist/stores/config-store.d.ts +14 -0
  104. package/packages/gateway/dist/stores/config-store.d.ts.map +1 -0
  105. package/packages/gateway/dist/stores/config-store.js +57 -0
  106. package/packages/gateway/dist/stores/config-store.js.map +1 -0
  107. package/packages/gateway/dist/stores/secret-vault.d.ts +23 -0
  108. package/packages/gateway/dist/stores/secret-vault.d.ts.map +1 -0
  109. package/packages/gateway/dist/stores/secret-vault.js +74 -0
  110. package/packages/gateway/dist/stores/secret-vault.js.map +1 -0
  111. package/packages/gateway/dist/tools/adapters.d.ts +8 -0
  112. package/packages/gateway/dist/tools/adapters.d.ts.map +1 -0
  113. package/packages/gateway/dist/tools/adapters.js +178 -0
  114. package/packages/gateway/dist/tools/adapters.js.map +1 -0
  115. package/packages/gateway/dist/tools/adb.d.ts +3 -0
  116. package/packages/gateway/dist/tools/adb.d.ts.map +1 -0
  117. package/packages/gateway/dist/tools/adb.js +60 -0
  118. package/packages/gateway/dist/tools/adb.js.map +1 -0
  119. package/packages/gateway/dist/tools/article.d.ts +3 -0
  120. package/packages/gateway/dist/tools/article.d.ts.map +1 -0
  121. package/packages/gateway/dist/tools/article.js +230 -0
  122. package/packages/gateway/dist/tools/article.js.map +1 -0
  123. package/packages/gateway/dist/tools/audit-approval.d.ts +4 -0
  124. package/packages/gateway/dist/tools/audit-approval.d.ts.map +1 -0
  125. package/packages/gateway/dist/tools/audit-approval.js +64 -0
  126. package/packages/gateway/dist/tools/audit-approval.js.map +1 -0
  127. package/packages/gateway/dist/tools/browser.d.ts +3 -0
  128. package/packages/gateway/dist/tools/browser.d.ts.map +1 -0
  129. package/packages/gateway/dist/tools/browser.js +55 -0
  130. package/packages/gateway/dist/tools/browser.js.map +1 -0
  131. package/packages/gateway/dist/tools/coding-agent.d.ts +3 -0
  132. package/packages/gateway/dist/tools/coding-agent.d.ts.map +1 -0
  133. package/packages/gateway/dist/tools/coding-agent.js +103 -0
  134. package/packages/gateway/dist/tools/coding-agent.js.map +1 -0
  135. package/packages/gateway/dist/tools/filesystem.d.ts +3 -0
  136. package/packages/gateway/dist/tools/filesystem.d.ts.map +1 -0
  137. package/packages/gateway/dist/tools/filesystem.js +141 -0
  138. package/packages/gateway/dist/tools/filesystem.js.map +1 -0
  139. package/packages/gateway/dist/tools/git.d.ts +3 -0
  140. package/packages/gateway/dist/tools/git.d.ts.map +1 -0
  141. package/packages/gateway/dist/tools/git.js +92 -0
  142. package/packages/gateway/dist/tools/git.js.map +1 -0
  143. package/packages/gateway/dist/tools/index.d.ts +4 -0
  144. package/packages/gateway/dist/tools/index.d.ts.map +1 -0
  145. package/packages/gateway/dist/tools/index.js +29 -0
  146. package/packages/gateway/dist/tools/index.js.map +1 -0
  147. package/packages/gateway/dist/tools/project.d.ts +3 -0
  148. package/packages/gateway/dist/tools/project.d.ts.map +1 -0
  149. package/packages/gateway/dist/tools/project.js +86 -0
  150. package/packages/gateway/dist/tools/project.js.map +1 -0
  151. package/packages/gateway/dist/tools/shell.d.ts +3 -0
  152. package/packages/gateway/dist/tools/shell.d.ts.map +1 -0
  153. package/packages/gateway/dist/tools/shell.js +98 -0
  154. package/packages/gateway/dist/tools/shell.js.map +1 -0
  155. package/packages/gateway/dist/tools/skill.d.ts +3 -0
  156. package/packages/gateway/dist/tools/skill.d.ts.map +1 -0
  157. package/packages/gateway/dist/tools/skill.js +231 -0
  158. package/packages/gateway/dist/tools/skill.js.map +1 -0
  159. package/packages/gateway/dist/tools/system.d.ts +3 -0
  160. package/packages/gateway/dist/tools/system.d.ts.map +1 -0
  161. package/packages/gateway/dist/tools/system.js +78 -0
  162. package/packages/gateway/dist/tools/system.js.map +1 -0
  163. package/packages/gateway/dist/util/exec.d.ts +21 -0
  164. package/packages/gateway/dist/util/exec.d.ts.map +1 -0
  165. package/packages/gateway/dist/util/exec.js +50 -0
  166. package/packages/gateway/dist/util/exec.js.map +1 -0
  167. package/packages/gateway/package.json +18 -0
  168. package/packages/mcp/dist/http-server.d.ts +16 -0
  169. package/packages/mcp/dist/http-server.d.ts.map +1 -0
  170. package/packages/mcp/dist/http-server.js +138 -0
  171. package/packages/mcp/dist/http-server.js.map +1 -0
  172. package/packages/mcp/dist/index.d.ts +4 -0
  173. package/packages/mcp/dist/index.d.ts.map +1 -0
  174. package/packages/mcp/dist/index.js +3 -0
  175. package/packages/mcp/dist/index.js.map +1 -0
  176. package/packages/mcp/dist/mcp-server.d.ts +9 -0
  177. package/packages/mcp/dist/mcp-server.d.ts.map +1 -0
  178. package/packages/mcp/dist/mcp-server.js +26 -0
  179. package/packages/mcp/dist/mcp-server.js.map +1 -0
  180. package/packages/mcp/package.json +18 -0
  181. package/packages/shared/dist/config.d.ts +314 -0
  182. package/packages/shared/dist/config.d.ts.map +1 -0
  183. package/packages/shared/dist/config.js +146 -0
  184. package/packages/shared/dist/config.js.map +1 -0
  185. package/packages/shared/dist/index.d.ts +8 -0
  186. package/packages/shared/dist/index.d.ts.map +1 -0
  187. package/packages/shared/dist/index.js +8 -0
  188. package/packages/shared/dist/index.js.map +1 -0
  189. package/packages/shared/dist/logger.d.ts +8 -0
  190. package/packages/shared/dist/logger.d.ts.map +1 -0
  191. package/packages/shared/dist/logger.js +26 -0
  192. package/packages/shared/dist/logger.js.map +1 -0
  193. package/packages/shared/dist/net.d.ts +10 -0
  194. package/packages/shared/dist/net.d.ts.map +1 -0
  195. package/packages/shared/dist/net.js +35 -0
  196. package/packages/shared/dist/net.js.map +1 -0
  197. package/packages/shared/dist/paths.d.ts +30 -0
  198. package/packages/shared/dist/paths.d.ts.map +1 -0
  199. package/packages/shared/dist/paths.js +70 -0
  200. package/packages/shared/dist/paths.js.map +1 -0
  201. package/packages/shared/dist/redaction.d.ts +15 -0
  202. package/packages/shared/dist/redaction.d.ts.map +1 -0
  203. package/packages/shared/dist/redaction.js +58 -0
  204. package/packages/shared/dist/redaction.js.map +1 -0
  205. package/packages/shared/dist/risk.d.ts +23 -0
  206. package/packages/shared/dist/risk.d.ts.map +1 -0
  207. package/packages/shared/dist/risk.js +28 -0
  208. package/packages/shared/dist/risk.js.map +1 -0
  209. package/packages/shared/dist/types.d.ts +94 -0
  210. package/packages/shared/dist/types.d.ts.map +1 -0
  211. package/packages/shared/dist/types.js +2 -0
  212. package/packages/shared/dist/types.js.map +1 -0
  213. package/packages/shared/package.json +13 -0
  214. package/packages/skill-sdk/dist/index.d.ts +36 -0
  215. package/packages/skill-sdk/dist/index.d.ts.map +1 -0
  216. package/packages/skill-sdk/dist/index.js +20 -0
  217. package/packages/skill-sdk/dist/index.js.map +1 -0
  218. package/packages/skill-sdk/package.json +14 -0
@@ -0,0 +1,310 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { SkillPermissionsSchema, } from "@localant/shared";
5
+ import { execFileSafe } from "../util/exec.js";
6
+ const RUNNER = fileURLToPath(new URL("../skill-runner.js", import.meta.url));
7
+ /**
8
+ * Loads, validates, enables/disables, runs and generates local skills.
9
+ * Generated skills are always saved disabled.
10
+ */
11
+ export class SkillRuntime {
12
+ paths;
13
+ secretResolver;
14
+ stateFile;
15
+ constructor(paths, secretResolver) {
16
+ this.paths = paths;
17
+ this.secretResolver = secretResolver;
18
+ this.stateFile = path.join(paths.root, "skills-state.json");
19
+ }
20
+ loadState() {
21
+ try {
22
+ return JSON.parse(fs.readFileSync(this.stateFile, "utf8"));
23
+ }
24
+ catch {
25
+ return { enabled: {} };
26
+ }
27
+ }
28
+ saveState(state) {
29
+ fs.writeFileSync(this.stateFile, JSON.stringify(state, null, 2), { mode: 0o600 });
30
+ }
31
+ /** Directories that may contain skills: the user skills dir + bundled examples. */
32
+ skillDirs() {
33
+ const dirs = [this.paths.skillsDir];
34
+ // bundled examples directory (when running from the repo / published package)
35
+ const bundled = fileURLToPath(new URL("../../../../examples/skills", import.meta.url));
36
+ if (fs.existsSync(bundled))
37
+ dirs.push(bundled);
38
+ return dirs;
39
+ }
40
+ list() {
41
+ const state = this.loadState();
42
+ const skills = [];
43
+ const seen = new Set();
44
+ for (const base of this.skillDirs()) {
45
+ if (!fs.existsSync(base))
46
+ continue;
47
+ for (const entry of fs.readdirSync(base, { withFileTypes: true })) {
48
+ if (!entry.isDirectory())
49
+ continue;
50
+ const dir = path.join(base, entry.name);
51
+ const manifestPath = path.join(dir, "skill.json");
52
+ if (!fs.existsSync(manifestPath))
53
+ continue;
54
+ const loaded = this.readManifest(manifestPath);
55
+ if (!loaded || seen.has(loaded.manifest.name))
56
+ continue;
57
+ seen.add(loaded.manifest.name);
58
+ const generated = fs.existsSync(path.join(dir, ".generated"));
59
+ skills.push({
60
+ manifest: loaded.manifest,
61
+ dir,
62
+ enabled: state.enabled[loaded.manifest.name] ?? false,
63
+ generated,
64
+ installedAt: this.installedAt(dir),
65
+ valid: loaded.errors.length === 0,
66
+ validationErrors: loaded.errors,
67
+ });
68
+ }
69
+ }
70
+ return skills.sort((a, b) => a.manifest.name.localeCompare(b.manifest.name));
71
+ }
72
+ get(name) {
73
+ return this.list().find((s) => s.manifest.name === name);
74
+ }
75
+ installedAt(dir) {
76
+ try {
77
+ return fs.statSync(dir).birthtime.toISOString();
78
+ }
79
+ catch {
80
+ return new Date().toISOString();
81
+ }
82
+ }
83
+ readManifest(manifestPath) {
84
+ let raw;
85
+ try {
86
+ raw = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
87
+ }
88
+ catch {
89
+ return undefined;
90
+ }
91
+ const errors = [];
92
+ const obj = raw;
93
+ if (typeof obj.name !== "string")
94
+ errors.push("Missing 'name'.");
95
+ if (typeof obj.version !== "string")
96
+ errors.push("Missing 'version'.");
97
+ if (typeof obj.entry !== "string")
98
+ errors.push("Missing 'entry'.");
99
+ if (!Array.isArray(obj.tools) || obj.tools.length === 0)
100
+ errors.push("Must declare at least one tool.");
101
+ let permissions;
102
+ try {
103
+ permissions = SkillPermissionsSchema.parse(obj.permissions ?? {});
104
+ }
105
+ catch {
106
+ permissions = SkillPermissionsSchema.parse({});
107
+ errors.push("Invalid 'permissions' block.");
108
+ }
109
+ const manifest = {
110
+ name: String(obj.name ?? "unknown"),
111
+ displayName: obj.displayName,
112
+ version: String(obj.version ?? "0.0.0"),
113
+ description: String(obj.description ?? ""),
114
+ author: obj.author,
115
+ license: obj.license,
116
+ entry: String(obj.entry ?? "src/index.ts"),
117
+ riskLevel: (typeof obj.riskLevel === "number" ? obj.riskLevel : 1),
118
+ permissions,
119
+ tools: (Array.isArray(obj.tools) ? obj.tools : []),
120
+ };
121
+ return { manifest, errors };
122
+ }
123
+ validate(name) {
124
+ const skill = this.get(name);
125
+ if (!skill)
126
+ return { valid: false, errors: [`Skill not found: ${name}`] };
127
+ const errors = [...skill.validationErrors];
128
+ const entry = path.join(skill.dir, skill.manifest.entry);
129
+ if (!fs.existsSync(entry))
130
+ errors.push(`Entry file missing: ${skill.manifest.entry}`);
131
+ if (!fs.existsSync(path.join(skill.dir, "README.md")))
132
+ errors.push("Missing README.md");
133
+ return { valid: errors.length === 0, errors };
134
+ }
135
+ setEnabled(name, enabled) {
136
+ const skill = this.get(name);
137
+ if (!skill)
138
+ throw new Error(`Skill not found: ${name}`);
139
+ if (enabled) {
140
+ const v = this.validate(name);
141
+ if (!v.valid)
142
+ throw new Error(`Cannot enable invalid skill: ${v.errors.join("; ")}`);
143
+ }
144
+ const state = this.loadState();
145
+ state.enabled[name] = enabled;
146
+ this.saveState(state);
147
+ return { ...skill, enabled };
148
+ }
149
+ /** Execute a tool inside a skill in an isolated subprocess. */
150
+ async run(name, tool, input) {
151
+ const skill = this.get(name);
152
+ if (!skill)
153
+ throw new Error(`Skill not found: ${name}`);
154
+ if (!skill.enabled)
155
+ throw new Error(`Skill '${name}' is disabled. Enable it after reviewing permissions.`);
156
+ const toolDef = skill.manifest.tools.find((t) => t.name === tool);
157
+ if (!toolDef)
158
+ throw new Error(`Tool '${tool}' not found in skill '${name}'.`);
159
+ const secrets = this.secretResolver(skill.manifest.permissions.secrets);
160
+ const payload = JSON.stringify({
161
+ entry: path.join(skill.dir, skill.manifest.entry),
162
+ tool,
163
+ input,
164
+ secrets,
165
+ workspaceDir: this.paths.workspaceDir,
166
+ });
167
+ const res = await execFileSafe(process.execPath, [RUNNER], {
168
+ input: payload,
169
+ timeoutMs: 60_000,
170
+ maxOutputBytes: 200_000,
171
+ env: { ...process.env, NODE_OPTIONS: "" },
172
+ });
173
+ if (res.code !== 0) {
174
+ throw new Error(`Skill execution failed: ${res.stderr || res.stdout || "unknown error"}`.trim());
175
+ }
176
+ const line = res.stdout.trim().split("\n").pop() ?? "{}";
177
+ const parsed = JSON.parse(line);
178
+ if (!parsed.ok)
179
+ throw new Error(parsed.error ?? "Skill returned an error.");
180
+ return parsed.result;
181
+ }
182
+ /** Create a skill skeleton on disk (always disabled). */
183
+ generate(input) {
184
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(input.name)) {
185
+ throw new Error(`Invalid skill name '${input.name}'. Use lowercase kebab-case.`);
186
+ }
187
+ const dir = path.join(this.paths.skillsDir, input.name);
188
+ if (fs.existsSync(dir))
189
+ throw new Error(`Skill '${input.name}' already exists.`);
190
+ fs.mkdirSync(path.join(dir, "src"), { recursive: true });
191
+ fs.mkdirSync(path.join(dir, "tests"), { recursive: true });
192
+ fs.mkdirSync(path.join(dir, "examples"), { recursive: true });
193
+ const permissions = SkillPermissionsSchema.parse(input.permissions ?? {});
194
+ const risk = (input.riskLevel ?? 1);
195
+ const toolName = `${input.name.replace(/-/g, "_")}_run`;
196
+ const manifest = {
197
+ name: input.name,
198
+ displayName: input.name,
199
+ version: "0.1.0",
200
+ description: input.description,
201
+ author: "local",
202
+ license: "MIT",
203
+ entry: "src/index.ts",
204
+ riskLevel: risk,
205
+ permissions,
206
+ tools: [
207
+ {
208
+ name: toolName,
209
+ description: input.description,
210
+ riskLevel: risk,
211
+ inputSchema: {
212
+ type: "object",
213
+ properties: { input: { type: "string" } },
214
+ required: [],
215
+ },
216
+ },
217
+ ],
218
+ };
219
+ fs.writeFileSync(path.join(dir, "skill.json"), JSON.stringify(manifest, null, 2));
220
+ fs.writeFileSync(path.join(dir, ".generated"), new Date().toISOString());
221
+ fs.writeFileSync(path.join(dir, "LICENSE"), "MIT\n");
222
+ fs.writeFileSync(path.join(dir, "CHANGELOG.md"), `# Changelog\n\n## 0.1.0\n- Generated skill skeleton.\n`);
223
+ fs.writeFileSync(path.join(dir, "README.md"), readmeTemplate(input.name, input.description, input.requirements ?? [], permissions, risk));
224
+ fs.writeFileSync(path.join(dir, "src", "index.ts"), skillSrcTemplate(input.name, toolName, input.requirements ?? []));
225
+ fs.writeFileSync(path.join(dir, "tests", "index.test.ts"), skillTestTemplate(input.name, toolName));
226
+ fs.writeFileSync(path.join(dir, "examples", "example.json"), JSON.stringify({ input: "hello" }, null, 2));
227
+ const state = this.get(input.name);
228
+ if (!state)
229
+ throw new Error("Generated skill could not be loaded.");
230
+ return state;
231
+ }
232
+ uninstall(name) {
233
+ const skill = this.get(name);
234
+ if (!skill)
235
+ return false;
236
+ if (!skill.dir.startsWith(this.paths.skillsDir)) {
237
+ throw new Error("Refusing to uninstall a bundled skill.");
238
+ }
239
+ fs.rmSync(skill.dir, { recursive: true, force: true });
240
+ const state = this.loadState();
241
+ delete state.enabled[name];
242
+ this.saveState(state);
243
+ return true;
244
+ }
245
+ }
246
+ function readmeTemplate(name, description, requirements, perms, risk) {
247
+ return `# ${name}
248
+
249
+ ${description}
250
+
251
+ > ⚠️ This skill was generated and is **disabled by default**. Review the permissions below, run \`skill_validate\`, then enable it from the dashboard or CLI.
252
+
253
+ ## Requirements
254
+ ${requirements.map((r) => `- ${r}`).join("\n") || "- (none specified)"}
255
+
256
+ ## Permissions
257
+ - filesystem: ${perms.filesystem.mode}
258
+ - shell: ${perms.shell.mode}
259
+ - network: ${perms.network.mode}${perms.network.allowedHosts.length ? ` (${perms.network.allowedHosts.join(", ")})` : ""}
260
+ - secrets: ${perms.secrets.join(", ") || "none"}
261
+ - risk level: ${risk}
262
+
263
+ ## Usage
264
+ Call the tool \`${name.replace(/-/g, "_")}_run\` from ChatGPT once enabled.
265
+ `;
266
+ }
267
+ function skillSrcTemplate(name, toolName, requirements) {
268
+ return `import { defineSkill, z } from "@localant/skill-sdk";
269
+
270
+ // Requirements:
271
+ ${requirements.map((r) => `// - ${r}`).join("\n") || "// - implement me"}
272
+
273
+ export default defineSkill({
274
+ name: "${name}",
275
+ tools: {
276
+ ${toolName}: {
277
+ description: "TODO: describe what this tool does",
278
+ riskLevel: 1,
279
+ inputSchema: z.object({
280
+ input: z.string().optional(),
281
+ }),
282
+ handler: async ({ input }, ctx) => {
283
+ ctx.log("running ${name}");
284
+ // TODO: implement. Use ctx.getSecret(name) for any declared secrets.
285
+ return { content: \`${name} received: \${input ?? ""}\` };
286
+ },
287
+ },
288
+ },
289
+ });
290
+ `;
291
+ }
292
+ function skillTestTemplate(name, toolName) {
293
+ return `import { describe, it, expect } from "vitest";
294
+ import skill from "../src/index";
295
+
296
+ describe("${name}", () => {
297
+ it("declares its tool", () => {
298
+ expect(skill.name).toBe("${name}");
299
+ expect(skill.tools.${toolName}).toBeDefined();
300
+ });
301
+
302
+ it("runs", async () => {
303
+ const ctx = { getSecret: async () => undefined, workspaceDir: ".", log: () => {} };
304
+ const out = await skill.tools.${toolName}.handler({ input: "x" } as any, ctx);
305
+ expect(out).toBeTruthy();
306
+ });
307
+ });
308
+ `;
309
+ }
310
+ //# sourceMappingURL=skill-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-runtime.js","sourceRoot":"","sources":["../../src/managers/skill-runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { type Config } from "@localant/shared";
2
+ export interface TunnelInfo {
3
+ provider: string;
4
+ url?: string;
5
+ status: "starting" | "running" | "stopped" | "error";
6
+ error?: string;
7
+ }
8
+ /**
9
+ * Starts a public tunnel to the local gateway so ChatGPT can reach /mcp.
10
+ * Order of preference: cloudflared → ngrok → user-provided publicUrl.
11
+ */
12
+ export declare class TunnelManager {
13
+ private readonly config;
14
+ private child?;
15
+ private info;
16
+ constructor(config: () => Config);
17
+ current(): TunnelInfo;
18
+ start(port: number): Promise<TunnelInfo>;
19
+ private startCloudflared;
20
+ private startNgrok;
21
+ stop(): void;
22
+ }
23
+ //# sourceMappingURL=tunnel-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel-manager.d.ts","sourceRoot":"","sources":["../../src/managers/tunnel-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAK7D,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,qBAAa,aAAa;IAIZ,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,KAAK,CAAC,CAAe;IAC7B,OAAO,CAAC,IAAI,CAAuD;gBAEtC,MAAM,EAAE,MAAM,MAAM;IAEjD,OAAO,IAAI,UAAU;IAIf,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAyB9C,OAAO,CAAC,gBAAgB;IA4BxB,OAAO,CAAC,UAAU;IA4BlB,IAAI,IAAI,IAAI;CAQb"}
@@ -0,0 +1,106 @@
1
+ import { spawn } from "node:child_process";
2
+ import { createLogger } from "@localant/shared";
3
+ import { commandExists } from "../util/exec.js";
4
+ const log = createLogger("tunnel");
5
+ /**
6
+ * Starts a public tunnel to the local gateway so ChatGPT can reach /mcp.
7
+ * Order of preference: cloudflared → ngrok → user-provided publicUrl.
8
+ */
9
+ export class TunnelManager {
10
+ config;
11
+ child;
12
+ info = { provider: "none", status: "stopped" };
13
+ constructor(config) {
14
+ this.config = config;
15
+ }
16
+ current() {
17
+ return this.info;
18
+ }
19
+ async start(port) {
20
+ const cfg = this.config().tunnel;
21
+ if (cfg.publicUrl) {
22
+ this.info = { provider: "user-provided", url: cfg.publicUrl, status: "running" };
23
+ return this.info;
24
+ }
25
+ if (cfg.provider === "cloudflared" && (await commandExists("cloudflared"))) {
26
+ return this.startCloudflared(port);
27
+ }
28
+ if (cfg.provider === "ngrok" && (await commandExists("ngrok"))) {
29
+ return this.startNgrok(port);
30
+ }
31
+ // Fallbacks
32
+ if (await commandExists("cloudflared"))
33
+ return this.startCloudflared(port);
34
+ if (await commandExists("ngrok"))
35
+ return this.startNgrok(port);
36
+ this.info = {
37
+ provider: "none",
38
+ status: "error",
39
+ error: "No tunnel provider found. Install cloudflared or ngrok, or set tunnel.publicUrl in config to a public HTTPS URL.",
40
+ };
41
+ return this.info;
42
+ }
43
+ startCloudflared(port) {
44
+ return new Promise((resolve) => {
45
+ this.info = { provider: "cloudflared", status: "starting" };
46
+ const child = spawn("cloudflared", ["tunnel", "--url", `http://127.0.0.1:${port}`], { shell: false });
47
+ this.child = child;
48
+ const onData = (buf) => {
49
+ const text = buf.toString("utf8");
50
+ const m = text.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/i);
51
+ if (m && this.info.status !== "running") {
52
+ this.info = { provider: "cloudflared", url: m[0], status: "running" };
53
+ resolve(this.info);
54
+ }
55
+ };
56
+ child.stdout.on("data", onData);
57
+ child.stderr.on("data", onData);
58
+ child.on("error", (e) => {
59
+ this.info = { provider: "cloudflared", status: "error", error: e.message };
60
+ resolve(this.info);
61
+ });
62
+ setTimeout(() => {
63
+ if (this.info.status !== "running") {
64
+ this.info = { provider: "cloudflared", status: "error", error: "Timed out waiting for tunnel URL." };
65
+ resolve(this.info);
66
+ }
67
+ }, 20_000);
68
+ });
69
+ }
70
+ startNgrok(port) {
71
+ return new Promise((resolve) => {
72
+ this.info = { provider: "ngrok", status: "starting" };
73
+ const child = spawn("ngrok", ["http", String(port), "--log", "stdout"], { shell: false });
74
+ this.child = child;
75
+ const onData = (buf) => {
76
+ const text = buf.toString("utf8");
77
+ const m = text.match(/https:\/\/[a-z0-9-]+\.ngrok[a-z0-9.-]*\.(app|io)/i);
78
+ if (m && this.info.status !== "running") {
79
+ this.info = { provider: "ngrok", url: m[0], status: "running" };
80
+ resolve(this.info);
81
+ }
82
+ };
83
+ child.stdout.on("data", onData);
84
+ child.stderr.on("data", onData);
85
+ child.on("error", (e) => {
86
+ this.info = { provider: "ngrok", status: "error", error: e.message };
87
+ resolve(this.info);
88
+ });
89
+ setTimeout(() => {
90
+ if (this.info.status !== "running") {
91
+ this.info = { provider: "ngrok", status: "error", error: "Timed out waiting for ngrok URL." };
92
+ resolve(this.info);
93
+ }
94
+ }, 20_000);
95
+ });
96
+ }
97
+ stop() {
98
+ if (this.child) {
99
+ log.info("stopping tunnel");
100
+ this.child.kill("SIGTERM");
101
+ this.child = undefined;
102
+ }
103
+ this.info = { provider: this.info.provider, status: "stopped" };
104
+ }
105
+ }
106
+ //# sourceMappingURL=tunnel-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel-manager.js","sourceRoot":"","sources":["../../src/managers/tunnel-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAe,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;AASnC;;;GAGG;AACH,MAAM,OAAO,aAAa;IAIK;IAHrB,KAAK,CAAgB;IACrB,IAAI,GAAe,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAEnE,YAA6B,MAAoB;QAApB,WAAM,GAAN,MAAM,CAAc;IAAG,CAAC;IAErD,OAAO;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAY;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC;QACjC,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;YAClB,IAAI,CAAC,IAAI,GAAG,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;YACjF,OAAO,IAAI,CAAC,IAAI,CAAC;QACnB,CAAC;QACD,IAAI,GAAG,CAAC,QAAQ,KAAK,aAAa,IAAI,CAAC,MAAM,aAAa,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;YAC3E,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;QACD,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YAC/D,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;QACD,YAAY;QACZ,IAAI,MAAM,aAAa,CAAC,aAAa,CAAC;YAAE,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAC3E,IAAI,MAAM,aAAa,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAE/D,IAAI,CAAC,IAAI,GAAG;YACV,QAAQ,EAAE,MAAM;YAChB,MAAM,EAAE,OAAO;YACf,KAAK,EACH,kHAAkH;SACrH,CAAC;QACF,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAEO,gBAAgB,CAAC,IAAY;QACnC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,CAAC,IAAI,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;YAC5D,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,oBAAoB,IAAI,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YACtG,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;YACnB,MAAM,MAAM,GAAG,CAAC,GAAW,EAAE,EAAE;gBAC7B,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAClC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;gBAClE,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;oBACxC,IAAI,CAAC,IAAI,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;oBACtE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC,CAAC;YACF,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAChC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAChC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;gBACtB,IAAI,CAAC,IAAI,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;gBAC3E,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC,CAAC,CAAC;YACH,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;oBACnC,IAAI,CAAC,IAAI,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,mCAAmC,EAAE,CAAC;oBACrG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC,EAAE,MAAM,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,UAAU,CAAC,IAAY;QAC7B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,CAAC,IAAI,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;YACtD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YAC1F,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;YACnB,MAAM,MAAM,GAAG,CAAC,GAAW,EAAE,EAAE;gBAC7B,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAClC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;gBAC1E,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;oBACxC,IAAI,CAAC,IAAI,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;oBAChE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC,CAAC;YACF,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAChC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAChC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;gBACtB,IAAI,CAAC,IAAI,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;gBACrE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC,CAAC,CAAC;YACH,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;oBACnC,IAAI,CAAC,IAAI,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,kCAAkC,EAAE,CAAC;oBAC9F,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC,EAAE,MAAM,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC3B,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,IAAI,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAClE,CAAC;CACF"}
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ import type { RiskLevel } from "@localant/shared";
3
+ /**
4
+ * A tool is generic over its Zod input schema `S`. Handlers receive the
5
+ * *output* type (`z.output<S>`), so `.default(...)` fields are non-optional.
6
+ */
7
+ export interface ToolDefinition<S extends z.ZodTypeAny = z.ZodTypeAny> {
8
+ name: string;
9
+ description: string;
10
+ risk: RiskLevel;
11
+ inputSchema: S;
12
+ /** Short human summary of an invocation, used for audit + approval prompts. */
13
+ summarize?: (input: z.output<S>) => string;
14
+ handler: (input: z.output<S>, ctx: ToolCallContext) => Promise<unknown> | unknown;
15
+ }
16
+ export interface ToolCallContext {
17
+ caller: string;
18
+ sessionId?: string;
19
+ }
20
+ /** In-memory registry of all tools the gateway exposes. */
21
+ export declare class ToolRegistry {
22
+ private readonly tools;
23
+ register<S extends z.ZodTypeAny>(def: ToolDefinition<S>): void;
24
+ unregister(name: string): void;
25
+ get(name: string): ToolDefinition | undefined;
26
+ list(): ToolDefinition[];
27
+ }
28
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;GAGG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,WAAW,EAAE,CAAC,CAAC;IACf,+EAA+E;IAC/E,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC;IAC3C,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CACnF;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,2DAA2D;AAC3D,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAE3D,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI;IAO9D,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI7C,IAAI,IAAI,cAAc,EAAE;CAGzB"}
@@ -0,0 +1,20 @@
1
+ /** In-memory registry of all tools the gateway exposes. */
2
+ export class ToolRegistry {
3
+ tools = new Map();
4
+ register(def) {
5
+ if (this.tools.has(def.name)) {
6
+ throw new Error(`Duplicate tool registration: ${def.name}`);
7
+ }
8
+ this.tools.set(def.name, def);
9
+ }
10
+ unregister(name) {
11
+ this.tools.delete(name);
12
+ }
13
+ get(name) {
14
+ return this.tools.get(name);
15
+ }
16
+ list() {
17
+ return [...this.tools.values()].sort((a, b) => a.name.localeCompare(b.name));
18
+ }
19
+ }
20
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAsBA,2DAA2D;AAC3D,MAAM,OAAO,YAAY;IACN,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;IAE3D,QAAQ,CAAyB,GAAsB;QACrD,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAgC,CAAC,CAAC;IAC7D,CAAC;IAED,UAAU,CAAC,IAAY;QACrB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/E,CAAC;CACF"}
@@ -0,0 +1,35 @@
1
+ export declare class CommandRejectedError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export interface ParsedCommand {
5
+ /** Whitespace-normalized full command. */
6
+ normalized: string;
7
+ /** Individual program words (first token of each pipeline/segment + args). */
8
+ tokens: string[];
9
+ }
10
+ /**
11
+ * Tokenize a command for safety inspection. We split on shell control
12
+ * operators so that `a && rm -rf /` is inspected as two segments, defeating
13
+ * naive "starts with allowed command" bypasses.
14
+ */
15
+ export declare function parseCommand(input: string): ParsedCommand;
16
+ export declare class CommandGuard {
17
+ private allowedCommands;
18
+ private blockedTokens;
19
+ constructor(allowedCommands: string[], blockedTokens: string[]);
20
+ setAllowed(commands: string[]): void;
21
+ setBlocked(tokens: string[]): void;
22
+ allowed(): string[];
23
+ /**
24
+ * Validate a command against the allowlist and blocklist. Throws on any
25
+ * rejection. Returns the normalized command on success.
26
+ *
27
+ * A command is allowed only if its normalized form *starts with* one of the
28
+ * allowlisted command prefixes AND contains no blocked tokens, no dangerous
29
+ * chaining/substitution metacharacters, and no piped second program.
30
+ */
31
+ assertAllowed(input: string): string;
32
+ /** Looser check for an *approved* arbitrary command — still blocks the hard blocklist. */
33
+ assertNotBlocked(input: string): string;
34
+ }
35
+ //# sourceMappingURL=command-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-guard.d.ts","sourceRoot":"","sources":["../../src/security/command-guard.ts"],"names":[],"mappings":"AAAA,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,aAAa;IAC5B,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAWzD;AAQD,qBAAa,YAAY;IAErB,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,aAAa;gBADb,eAAe,EAAE,MAAM,EAAE,EACzB,aAAa,EAAE,MAAM,EAAE;IAGjC,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI;IAGpC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI;IAGlC,OAAO,IAAI,MAAM,EAAE;IAInB;;;;;;;OAOG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IA0CpC,0FAA0F;IAC1F,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAaxC"}