@ikarmic/forge-core 5.0.0 → 5.1.1
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.
- package/README.md +1 -1
- package/dist/agent/agent.d.ts +8 -0
- package/dist/agent/agent.js +148 -24
- package/dist/agent/background.d.ts +58 -0
- package/dist/agent/background.js +139 -0
- package/dist/agent/enhance-prompt.d.ts +3 -1
- package/dist/agent/enhance-prompt.js +6 -2
- package/dist/agent/goal.d.ts +54 -0
- package/dist/agent/goal.js +65 -0
- package/dist/agent/prompts.d.ts +25 -1
- package/dist/agent/prompts.js +61 -17
- package/dist/agents/agent-files.d.ts +43 -0
- package/dist/agents/agent-files.js +109 -0
- package/dist/checkpoints/store.js +5 -1
- package/dist/commands/custom-commands.d.ts +9 -4
- package/dist/commands/custom-commands.js +13 -2
- package/dist/config-file.d.ts +43 -0
- package/dist/config-file.js +249 -5
- package/dist/config-merge.d.ts +13 -0
- package/dist/config-merge.js +67 -0
- package/dist/config-schema.d.ts +340 -0
- package/dist/config-schema.js +126 -0
- package/dist/config.js +2 -1
- package/dist/context/compaction.js +4 -0
- package/dist/context/mask.js +1 -1
- package/dist/custom-providers.d.ts +95 -0
- package/dist/custom-providers.js +120 -0
- package/dist/git/auto-commit.d.ts +2 -2
- package/dist/git/auto-commit.js +5 -4
- package/dist/github/github-tools.d.ts +2 -2
- package/dist/hooks/runner.js +3 -2
- package/dist/import/claude-code.d.ts +39 -0
- package/dist/import/claude-code.js +254 -0
- package/dist/index.d.ts +34 -5
- package/dist/index.js +27 -4
- package/dist/journey/answers-block.d.ts +17 -0
- package/dist/journey/answers-block.js +15 -0
- package/dist/journey/index.d.ts +9 -0
- package/dist/journey/index.js +8 -0
- package/dist/journey/journey.d.ts +13 -0
- package/dist/journey/journey.js +40 -0
- package/dist/journey/offer.d.ts +25 -0
- package/dist/journey/offer.js +48 -0
- package/dist/journey/questions.d.ts +23 -0
- package/dist/journey/questions.js +49 -0
- package/dist/journey/stages.d.ts +13 -0
- package/dist/journey/stages.js +107 -0
- package/dist/journey/survey.d.ts +10 -0
- package/dist/journey/survey.js +203 -0
- package/dist/journey/trigger.d.ts +19 -0
- package/dist/journey/trigger.js +79 -0
- package/dist/journey/types.d.ts +72 -0
- package/dist/journey/types.js +1 -0
- package/dist/lsp/client.d.ts +5 -0
- package/dist/lsp/client.js +39 -3
- package/dist/mcp/index.d.ts +5 -1
- package/dist/mcp/index.js +3 -1
- package/dist/mcp/manager.d.ts +17 -3
- package/dist/mcp/manager.js +27 -2
- package/dist/mcp/marketplace.d.ts +2 -0
- package/dist/mcp/marketplace.js +10 -4
- package/dist/mcp/mcp-client.d.ts +12 -2
- package/dist/mcp/mcp-client.js +74 -17
- package/dist/mcp/mcp-config.d.ts +2 -0
- package/dist/mcp/mcp-config.js +1 -0
- package/dist/mcp/oauth.d.ts +55 -0
- package/dist/mcp/oauth.js +197 -0
- package/dist/mcp/resource-tools.d.ts +8 -0
- package/dist/mcp/resource-tools.js +56 -0
- package/dist/memory/session-digest.d.ts +12 -0
- package/dist/memory/session-digest.js +47 -0
- package/dist/memory/stale.js +2 -1
- package/dist/model-alias.d.ts +18 -2
- package/dist/model-alias.js +27 -3
- package/dist/model-catalog.js +0 -1
- package/dist/model-list.js +2 -1
- package/dist/model-overrides.d.ts +30 -0
- package/dist/model-overrides.js +48 -0
- package/dist/orchestrator/specialists-registry.js +2 -3
- package/dist/orchestrator/specialists.js +4 -4
- package/dist/policy/ca-certs.d.ts +8 -0
- package/dist/policy/ca-certs.js +30 -0
- package/dist/policy/proxy.d.ts +10 -3
- package/dist/policy/proxy.js +33 -6
- package/dist/pricing.js +4 -0
- package/dist/providers.d.ts +7 -0
- package/dist/providers.js +39 -5
- package/dist/semantic/embedder.d.ts +15 -0
- package/dist/semantic/embedder.js +25 -0
- package/dist/semantic/semantic-index.d.ts +10 -2
- package/dist/semantic/semantic-index.js +16 -7
- package/dist/sessions/session-store.js +2 -1
- package/dist/skills/builtin.d.ts +2 -0
- package/dist/skills/builtin.js +68 -0
- package/dist/skills/index.d.ts +2 -0
- package/dist/skills/index.js +2 -0
- package/dist/skills/loader.d.ts +10 -3
- package/dist/skills/loader.js +20 -7
- package/dist/skills/marketplace.js +2 -1
- package/dist/skills/remote.d.ts +14 -0
- package/dist/skills/remote.js +131 -0
- package/dist/skills/types.d.ts +10 -0
- package/dist/specs/generate.d.ts +18 -9
- package/dist/specs/generate.js +174 -14
- package/dist/specs/index.d.ts +2 -2
- package/dist/specs/index.js +1 -1
- package/dist/specs/store.d.ts +14 -2
- package/dist/specs/store.js +26 -1
- package/dist/specs/types.d.ts +11 -0
- package/dist/steering/extra-instructions.d.ts +8 -0
- package/dist/steering/extra-instructions.js +104 -0
- package/dist/steering/folder-instructions.d.ts +8 -0
- package/dist/steering/folder-instructions.js +28 -0
- package/dist/steering/select.js +2 -1
- package/dist/timed-fetch.d.ts +12 -0
- package/dist/timed-fetch.js +83 -0
- package/dist/tools/apply-patch.d.ts +52 -0
- package/dist/tools/apply-patch.js +197 -0
- package/dist/tools/ask-user.d.ts +27 -0
- package/dist/tools/ask-user.js +60 -0
- package/dist/tools/browser-tools.d.ts +6 -6
- package/dist/tools/browser-tools.js +3 -13
- package/dist/tools/codebase-search.d.ts +4 -2
- package/dist/tools/codebase-search.js +2 -2
- package/dist/tools/edit-file.js +5 -3
- package/dist/tools/fetch-url.d.ts +7 -0
- package/dist/tools/fetch-url.js +52 -19
- package/dist/tools/find-symbol.d.ts +2 -2
- package/dist/tools/ignore-rules.js +2 -1
- package/dist/tools/index.d.ts +5 -1
- package/dist/tools/index.js +10 -1
- package/dist/tools/memory.d.ts +6 -6
- package/dist/tools/notebook.d.ts +2 -2
- package/dist/tools/permission-rules.d.ts +32 -0
- package/dist/tools/permission-rules.js +182 -0
- package/dist/tools/read-file.d.ts +5 -0
- package/dist/tools/read-file.js +12 -2
- package/dist/tools/read-only.d.ts +1 -1
- package/dist/tools/read-only.js +2 -0
- package/dist/tools/run-command.d.ts +4 -2
- package/dist/tools/run-command.js +12 -8
- package/dist/tools/sandbox-loader.js +3 -13
- package/dist/tools/search-files.d.ts +8 -2
- package/dist/tools/search-files.js +43 -0
- package/dist/tools/shared.d.ts +5 -0
- package/dist/tools/shared.js +30 -2
- package/dist/tools/shell-env.d.ts +7 -0
- package/dist/tools/shell-env.js +9 -0
- package/dist/tools/sub-agent-wait.d.ts +29 -0
- package/dist/tools/sub-agent-wait.js +60 -0
- package/dist/tools/sub-agent.d.ts +50 -4
- package/dist/tools/sub-agent.js +213 -125
- package/dist/tools/text-encoding.d.ts +10 -0
- package/dist/tools/text-encoding.js +40 -0
- package/dist/tools/todo.d.ts +36 -0
- package/dist/tools/todo.js +42 -0
- package/dist/tools/write-file.js +15 -9
- package/dist/tools/write-tools.d.ts +12 -0
- package/dist/tools/write-tools.js +18 -0
- package/dist/types.d.ts +98 -0
- package/dist/worktree/worktree.d.ts +3 -0
- package/dist/worktree/worktree.js +22 -0
- package/package.json +1 -1
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import type { ForgeConfigFile } from './config-file.js';
|
|
2
|
+
/** Compile-time proof that the schema below covers every key of `ForgeConfigFile`: add a key there and this stops compiling. */
|
|
3
|
+
export declare const CONFIG_KEY_COVERAGE: Record<keyof ForgeConfigFile, true>;
|
|
4
|
+
/** JSON Schema (draft-07) for `~/.forge/config.json` and `<workspace>/.forge/config.json`. */
|
|
5
|
+
export declare const FORGE_CONFIG_SCHEMA: {
|
|
6
|
+
readonly $schema: "http://json-schema.org/draft-07/schema#";
|
|
7
|
+
readonly title: "Ikarmic Forge config";
|
|
8
|
+
readonly type: "object";
|
|
9
|
+
readonly additionalProperties: false;
|
|
10
|
+
readonly properties: {
|
|
11
|
+
readonly provider: {
|
|
12
|
+
readonly description: "The model provider to use.";
|
|
13
|
+
readonly enum: readonly import("./types.js").ProviderName[];
|
|
14
|
+
};
|
|
15
|
+
readonly model: {
|
|
16
|
+
readonly type: "string";
|
|
17
|
+
readonly description: "The model id, an alias, or provider:model.";
|
|
18
|
+
};
|
|
19
|
+
readonly completionModel: {
|
|
20
|
+
readonly type: "string";
|
|
21
|
+
readonly description: "Model for inline completion; empty uses the main model.";
|
|
22
|
+
};
|
|
23
|
+
readonly compactionModel: {
|
|
24
|
+
readonly type: "string";
|
|
25
|
+
readonly description: "Model that writes the summary when a long chat is condensed; empty uses the main model.";
|
|
26
|
+
};
|
|
27
|
+
readonly disabledProviders: {
|
|
28
|
+
readonly type: "array";
|
|
29
|
+
readonly description: "Providers hidden from the model picker.";
|
|
30
|
+
readonly items: {
|
|
31
|
+
readonly enum: readonly import("./types.js").ProviderName[];
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
readonly reasoningEffort: {
|
|
35
|
+
readonly enum: readonly ["none", "minimal", "low", "medium", "high", "xhigh"];
|
|
36
|
+
readonly description: "Reasoning effort for models that support it.";
|
|
37
|
+
};
|
|
38
|
+
readonly autoApproveTools: {
|
|
39
|
+
readonly description: "Tools that run without asking. Default: the read-only tools. Destructive tools always ask. User config only.";
|
|
40
|
+
readonly type: "array";
|
|
41
|
+
readonly items: {
|
|
42
|
+
readonly type: "string";
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
readonly autoApproveCommands: {
|
|
46
|
+
readonly type: "object";
|
|
47
|
+
readonly description: "Commands you chose \"Always allow\", per workspace path. Written by Forge; user config only.";
|
|
48
|
+
readonly additionalProperties: {
|
|
49
|
+
readonly type: "array";
|
|
50
|
+
readonly items: {
|
|
51
|
+
readonly type: "object";
|
|
52
|
+
readonly properties: {
|
|
53
|
+
readonly command: {
|
|
54
|
+
readonly type: "string";
|
|
55
|
+
};
|
|
56
|
+
readonly fingerprint: {
|
|
57
|
+
readonly type: "string";
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
readonly required: readonly ["command"];
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
readonly permission: {
|
|
65
|
+
readonly type: "object";
|
|
66
|
+
readonly description: "Ordered permission rules. Each permission (read, edit, bash, webfetch, websearch, task, external_directory) is an action or a pattern to action map; the last matching rule wins. A project file can only tighten (ask, deny).";
|
|
67
|
+
readonly additionalProperties: {
|
|
68
|
+
readonly oneOf: readonly [{
|
|
69
|
+
readonly enum: readonly ["allow", "ask", "deny"];
|
|
70
|
+
}, {
|
|
71
|
+
readonly type: "object";
|
|
72
|
+
readonly additionalProperties: {
|
|
73
|
+
readonly enum: readonly ["allow", "ask", "deny"];
|
|
74
|
+
};
|
|
75
|
+
}];
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
readonly customProviders: {
|
|
79
|
+
readonly type: "object";
|
|
80
|
+
readonly description: "Providers beyond the built-in ones, by id. A preset id (groq, deepseek, mistral, ...) needs only a key; any other id needs a baseUrl. A model on one is written id:model. User config only.";
|
|
81
|
+
readonly additionalProperties: {
|
|
82
|
+
readonly type: "object";
|
|
83
|
+
readonly properties: {
|
|
84
|
+
readonly name: {
|
|
85
|
+
readonly type: "string";
|
|
86
|
+
};
|
|
87
|
+
readonly baseUrl: {
|
|
88
|
+
readonly type: "string";
|
|
89
|
+
readonly format: "uri";
|
|
90
|
+
};
|
|
91
|
+
readonly apiKey: {
|
|
92
|
+
readonly type: "string";
|
|
93
|
+
readonly description: "Stored as plain text; prefer apiKeyEnv.";
|
|
94
|
+
};
|
|
95
|
+
readonly apiKeyEnv: {
|
|
96
|
+
readonly type: "string";
|
|
97
|
+
readonly description: "Name of the environment variable that holds the key.";
|
|
98
|
+
};
|
|
99
|
+
readonly headers: {
|
|
100
|
+
readonly type: "object";
|
|
101
|
+
readonly additionalProperties: {
|
|
102
|
+
readonly type: "string";
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
readonly api: {
|
|
106
|
+
readonly enum: readonly ["openai-compatible", "anthropic"];
|
|
107
|
+
};
|
|
108
|
+
readonly timeoutMs: {
|
|
109
|
+
readonly type: "integer";
|
|
110
|
+
readonly minimum: 1;
|
|
111
|
+
};
|
|
112
|
+
readonly chunkTimeoutMs: {
|
|
113
|
+
readonly type: "integer";
|
|
114
|
+
readonly minimum: 1;
|
|
115
|
+
};
|
|
116
|
+
readonly models: {
|
|
117
|
+
readonly type: "object";
|
|
118
|
+
readonly additionalProperties: {
|
|
119
|
+
readonly type: "object";
|
|
120
|
+
readonly properties: {
|
|
121
|
+
readonly id: {
|
|
122
|
+
readonly type: "string";
|
|
123
|
+
readonly description: "The id sent to the API when it differs from the key here.";
|
|
124
|
+
};
|
|
125
|
+
readonly name: {
|
|
126
|
+
readonly type: "string";
|
|
127
|
+
};
|
|
128
|
+
readonly limit: {
|
|
129
|
+
readonly type: "object";
|
|
130
|
+
readonly properties: {
|
|
131
|
+
readonly context: {
|
|
132
|
+
readonly type: "integer";
|
|
133
|
+
readonly minimum: 1;
|
|
134
|
+
};
|
|
135
|
+
readonly output: {
|
|
136
|
+
readonly type: "integer";
|
|
137
|
+
readonly minimum: 1;
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
readonly additionalProperties: false;
|
|
141
|
+
};
|
|
142
|
+
readonly cost: {
|
|
143
|
+
readonly type: "object";
|
|
144
|
+
readonly description: "Price per million tokens.";
|
|
145
|
+
readonly properties: {
|
|
146
|
+
readonly input: {
|
|
147
|
+
readonly type: "number";
|
|
148
|
+
readonly minimum: 0;
|
|
149
|
+
};
|
|
150
|
+
readonly output: {
|
|
151
|
+
readonly type: "number";
|
|
152
|
+
readonly minimum: 0;
|
|
153
|
+
};
|
|
154
|
+
};
|
|
155
|
+
readonly additionalProperties: false;
|
|
156
|
+
};
|
|
157
|
+
readonly toolCall: {
|
|
158
|
+
readonly type: "boolean";
|
|
159
|
+
};
|
|
160
|
+
readonly reasoning: {
|
|
161
|
+
readonly type: "boolean";
|
|
162
|
+
};
|
|
163
|
+
readonly modalities: {
|
|
164
|
+
readonly type: "object";
|
|
165
|
+
readonly properties: {
|
|
166
|
+
readonly input: {
|
|
167
|
+
readonly type: "array";
|
|
168
|
+
readonly items: {
|
|
169
|
+
readonly type: "string";
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
readonly output: {
|
|
173
|
+
readonly type: "array";
|
|
174
|
+
readonly items: {
|
|
175
|
+
readonly type: "string";
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
readonly required: readonly ["input", "output"];
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
readonly whitelist: {
|
|
185
|
+
readonly type: "array";
|
|
186
|
+
readonly items: {
|
|
187
|
+
readonly type: "string";
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
readonly blacklist: {
|
|
191
|
+
readonly type: "array";
|
|
192
|
+
readonly items: {
|
|
193
|
+
readonly type: "string";
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
};
|
|
199
|
+
readonly modelOverrides: {
|
|
200
|
+
readonly type: "object";
|
|
201
|
+
readonly description: "Context and output limits and prices per model, keyed provider:model, id:model or a bare model id.";
|
|
202
|
+
readonly additionalProperties: {
|
|
203
|
+
readonly type: "object";
|
|
204
|
+
readonly properties: {
|
|
205
|
+
readonly limit: {
|
|
206
|
+
readonly type: "object";
|
|
207
|
+
readonly properties: {
|
|
208
|
+
readonly context: {
|
|
209
|
+
readonly type: "integer";
|
|
210
|
+
readonly minimum: 1;
|
|
211
|
+
};
|
|
212
|
+
readonly output: {
|
|
213
|
+
readonly type: "integer";
|
|
214
|
+
readonly minimum: 1;
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
readonly additionalProperties: false;
|
|
218
|
+
};
|
|
219
|
+
readonly cost: {
|
|
220
|
+
readonly type: "object";
|
|
221
|
+
readonly description: "Price per million tokens.";
|
|
222
|
+
readonly properties: {
|
|
223
|
+
readonly input: {
|
|
224
|
+
readonly type: "number";
|
|
225
|
+
readonly minimum: 0;
|
|
226
|
+
};
|
|
227
|
+
readonly output: {
|
|
228
|
+
readonly type: "number";
|
|
229
|
+
readonly minimum: 0;
|
|
230
|
+
};
|
|
231
|
+
};
|
|
232
|
+
readonly additionalProperties: false;
|
|
233
|
+
};
|
|
234
|
+
};
|
|
235
|
+
readonly additionalProperties: false;
|
|
236
|
+
};
|
|
237
|
+
};
|
|
238
|
+
readonly modelFilters: {
|
|
239
|
+
readonly type: "object";
|
|
240
|
+
readonly description: "Per provider, which model ids the pickers list: whitelist (only these), then blacklist (not these).";
|
|
241
|
+
readonly additionalProperties: {
|
|
242
|
+
readonly type: "object";
|
|
243
|
+
readonly properties: {
|
|
244
|
+
readonly whitelist: {
|
|
245
|
+
readonly type: "array";
|
|
246
|
+
readonly items: {
|
|
247
|
+
readonly type: "string";
|
|
248
|
+
};
|
|
249
|
+
};
|
|
250
|
+
readonly blacklist: {
|
|
251
|
+
readonly type: "array";
|
|
252
|
+
readonly items: {
|
|
253
|
+
readonly type: "string";
|
|
254
|
+
};
|
|
255
|
+
};
|
|
256
|
+
};
|
|
257
|
+
readonly additionalProperties: false;
|
|
258
|
+
};
|
|
259
|
+
};
|
|
260
|
+
readonly subagentModel: {
|
|
261
|
+
readonly type: "string";
|
|
262
|
+
readonly description: "The model sub-agents use when the model does not name one; empty means the chat model.";
|
|
263
|
+
};
|
|
264
|
+
readonly instructions: {
|
|
265
|
+
readonly description: "Extra instruction sources added to the system prompt: files, globs (relative to the workspace) and http(s) URLs. User config only.";
|
|
266
|
+
readonly type: "array";
|
|
267
|
+
readonly items: {
|
|
268
|
+
readonly type: "string";
|
|
269
|
+
};
|
|
270
|
+
};
|
|
271
|
+
readonly skillPaths: {
|
|
272
|
+
readonly description: "Extra places to read skills from: folders (absolute, ~/..., or relative to the workspace) or http(s) URLs of a skill file or a skill index. User config only.";
|
|
273
|
+
readonly type: "array";
|
|
274
|
+
readonly items: {
|
|
275
|
+
readonly type: "string";
|
|
276
|
+
};
|
|
277
|
+
};
|
|
278
|
+
readonly caCertificates: {
|
|
279
|
+
readonly description: "PEM files of extra certificate authorities to trust (absolute or ~/...), for networks that re-sign TLS. Needs a window reload. User config only.";
|
|
280
|
+
readonly type: "array";
|
|
281
|
+
readonly items: {
|
|
282
|
+
readonly type: "string";
|
|
283
|
+
};
|
|
284
|
+
};
|
|
285
|
+
readonly aliases: {
|
|
286
|
+
readonly type: "object";
|
|
287
|
+
readonly description: "Short names for models, for example \"fast\": \"anthropic:claude-haiku-4-5\".";
|
|
288
|
+
readonly additionalProperties: {
|
|
289
|
+
readonly type: "string";
|
|
290
|
+
};
|
|
291
|
+
};
|
|
292
|
+
readonly modeModels: {
|
|
293
|
+
readonly type: "object";
|
|
294
|
+
readonly description: "Model for a chat mode that has none of its own: mode id to model.";
|
|
295
|
+
readonly additionalProperties: {
|
|
296
|
+
readonly type: "string";
|
|
297
|
+
};
|
|
298
|
+
};
|
|
299
|
+
readonly sessionRetentionDays: {
|
|
300
|
+
readonly type: "integer";
|
|
301
|
+
readonly minimum: 1;
|
|
302
|
+
readonly description: "Delete saved chats not updated for this many days when the extension starts. Unset keeps everything. User config only.";
|
|
303
|
+
};
|
|
304
|
+
readonly display: {
|
|
305
|
+
readonly type: "object";
|
|
306
|
+
readonly description: "How blocks in the chat are shown.";
|
|
307
|
+
readonly properties: {
|
|
308
|
+
readonly blockDefault: {
|
|
309
|
+
readonly enum: readonly ["collapsed", "expanded"];
|
|
310
|
+
};
|
|
311
|
+
readonly detail: {
|
|
312
|
+
readonly enum: readonly ["compact", "full"];
|
|
313
|
+
};
|
|
314
|
+
readonly showReasoning: {
|
|
315
|
+
readonly type: "boolean";
|
|
316
|
+
};
|
|
317
|
+
readonly blocks: {
|
|
318
|
+
readonly type: "object";
|
|
319
|
+
readonly description: "Per kind of block: reasoning, terminal (command output), edit (file edits), mcp (MCP tool results).";
|
|
320
|
+
readonly properties: {
|
|
321
|
+
readonly reasoning: {
|
|
322
|
+
readonly enum: readonly ["hidden", "collapsed", "expanded"];
|
|
323
|
+
};
|
|
324
|
+
readonly terminal: {
|
|
325
|
+
readonly enum: readonly ["collapsed", "expanded"];
|
|
326
|
+
};
|
|
327
|
+
readonly edit: {
|
|
328
|
+
readonly enum: readonly ["collapsed", "expanded"];
|
|
329
|
+
};
|
|
330
|
+
readonly mcp: {
|
|
331
|
+
readonly enum: readonly ["collapsed", "expanded"];
|
|
332
|
+
};
|
|
333
|
+
};
|
|
334
|
+
readonly additionalProperties: false;
|
|
335
|
+
};
|
|
336
|
+
};
|
|
337
|
+
readonly additionalProperties: false;
|
|
338
|
+
};
|
|
339
|
+
};
|
|
340
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { SUPPORTED_PROVIDERS } from './config.js';
|
|
2
|
+
/** Compile-time proof that the schema below covers every key of `ForgeConfigFile`: add a key there and this stops compiling. */
|
|
3
|
+
export const CONFIG_KEY_COVERAGE = {
|
|
4
|
+
provider: true,
|
|
5
|
+
model: true,
|
|
6
|
+
completionModel: true,
|
|
7
|
+
compactionModel: true,
|
|
8
|
+
disabledProviders: true,
|
|
9
|
+
reasoningEffort: true,
|
|
10
|
+
autoApproveTools: true,
|
|
11
|
+
autoApproveCommands: true,
|
|
12
|
+
permission: true,
|
|
13
|
+
customProviders: true,
|
|
14
|
+
modelOverrides: true,
|
|
15
|
+
modelFilters: true,
|
|
16
|
+
subagentModel: true,
|
|
17
|
+
instructions: true,
|
|
18
|
+
skillPaths: true,
|
|
19
|
+
caCertificates: true,
|
|
20
|
+
aliases: true,
|
|
21
|
+
modeModels: true,
|
|
22
|
+
sessionRetentionDays: true,
|
|
23
|
+
display: true,
|
|
24
|
+
};
|
|
25
|
+
const strings = { type: 'array', items: { type: 'string' } };
|
|
26
|
+
const limit = { type: 'object', properties: { context: { type: 'integer', minimum: 1 }, output: { type: 'integer', minimum: 1 } }, additionalProperties: false };
|
|
27
|
+
const cost = { type: 'object', description: 'Price per million tokens.', properties: { input: { type: 'number', minimum: 0 }, output: { type: 'number', minimum: 0 } }, additionalProperties: false };
|
|
28
|
+
const action = { enum: ['allow', 'ask', 'deny'] };
|
|
29
|
+
/** JSON Schema (draft-07) for `~/.forge/config.json` and `<workspace>/.forge/config.json`. */
|
|
30
|
+
export const FORGE_CONFIG_SCHEMA = {
|
|
31
|
+
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
32
|
+
title: 'Ikarmic Forge config',
|
|
33
|
+
type: 'object',
|
|
34
|
+
additionalProperties: false,
|
|
35
|
+
properties: {
|
|
36
|
+
provider: { description: 'The model provider to use.', enum: [...SUPPORTED_PROVIDERS] },
|
|
37
|
+
model: { type: 'string', description: 'The model id, an alias, or provider:model.' },
|
|
38
|
+
completionModel: { type: 'string', description: 'Model for inline completion; empty uses the main model.' },
|
|
39
|
+
compactionModel: { type: 'string', description: 'Model that writes the summary when a long chat is condensed; empty uses the main model.' },
|
|
40
|
+
disabledProviders: { type: 'array', description: 'Providers hidden from the model picker.', items: { enum: [...SUPPORTED_PROVIDERS] } },
|
|
41
|
+
reasoningEffort: { enum: ['none', 'minimal', 'low', 'medium', 'high', 'xhigh'], description: 'Reasoning effort for models that support it.' },
|
|
42
|
+
autoApproveTools: { ...strings, description: 'Tools that run without asking. Default: the read-only tools. Destructive tools always ask. User config only.' },
|
|
43
|
+
autoApproveCommands: {
|
|
44
|
+
type: 'object',
|
|
45
|
+
description: 'Commands you chose "Always allow", per workspace path. Written by Forge; user config only.',
|
|
46
|
+
additionalProperties: { type: 'array', items: { type: 'object', properties: { command: { type: 'string' }, fingerprint: { type: 'string' } }, required: ['command'] } },
|
|
47
|
+
},
|
|
48
|
+
permission: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
description: 'Ordered permission rules. Each permission (read, edit, bash, webfetch, websearch, task, external_directory) is an action or a pattern to action map; the last matching rule wins. A project file can only tighten (ask, deny).',
|
|
51
|
+
additionalProperties: { oneOf: [action, { type: 'object', additionalProperties: action }] },
|
|
52
|
+
},
|
|
53
|
+
customProviders: {
|
|
54
|
+
type: 'object',
|
|
55
|
+
description: 'Providers beyond the built-in ones, by id. A preset id (groq, deepseek, mistral, ...) needs only a key; any other id needs a baseUrl. A model on one is written id:model. User config only.',
|
|
56
|
+
additionalProperties: {
|
|
57
|
+
type: 'object',
|
|
58
|
+
properties: {
|
|
59
|
+
name: { type: 'string' },
|
|
60
|
+
baseUrl: { type: 'string', format: 'uri' },
|
|
61
|
+
apiKey: { type: 'string', description: 'Stored as plain text; prefer apiKeyEnv.' },
|
|
62
|
+
apiKeyEnv: { type: 'string', description: 'Name of the environment variable that holds the key.' },
|
|
63
|
+
headers: { type: 'object', additionalProperties: { type: 'string' } },
|
|
64
|
+
api: { enum: ['openai-compatible', 'anthropic'] },
|
|
65
|
+
timeoutMs: { type: 'integer', minimum: 1 },
|
|
66
|
+
chunkTimeoutMs: { type: 'integer', minimum: 1 },
|
|
67
|
+
models: {
|
|
68
|
+
type: 'object',
|
|
69
|
+
additionalProperties: {
|
|
70
|
+
type: 'object',
|
|
71
|
+
properties: {
|
|
72
|
+
id: { type: 'string', description: 'The id sent to the API when it differs from the key here.' },
|
|
73
|
+
name: { type: 'string' },
|
|
74
|
+
limit,
|
|
75
|
+
cost,
|
|
76
|
+
toolCall: { type: 'boolean' },
|
|
77
|
+
reasoning: { type: 'boolean' },
|
|
78
|
+
modalities: { type: 'object', properties: { input: strings, output: strings }, required: ['input', 'output'] },
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
whitelist: strings,
|
|
83
|
+
blacklist: strings,
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
modelOverrides: {
|
|
88
|
+
type: 'object',
|
|
89
|
+
description: 'Context and output limits and prices per model, keyed provider:model, id:model or a bare model id.',
|
|
90
|
+
additionalProperties: { type: 'object', properties: { limit, cost }, additionalProperties: false },
|
|
91
|
+
},
|
|
92
|
+
modelFilters: {
|
|
93
|
+
type: 'object',
|
|
94
|
+
description: 'Per provider, which model ids the pickers list: whitelist (only these), then blacklist (not these).',
|
|
95
|
+
additionalProperties: { type: 'object', properties: { whitelist: strings, blacklist: strings }, additionalProperties: false },
|
|
96
|
+
},
|
|
97
|
+
subagentModel: { type: 'string', description: 'The model sub-agents use when the model does not name one; empty means the chat model.' },
|
|
98
|
+
instructions: { ...strings, description: 'Extra instruction sources added to the system prompt: files, globs (relative to the workspace) and http(s) URLs. User config only.' },
|
|
99
|
+
skillPaths: { ...strings, description: 'Extra places to read skills from: folders (absolute, ~/..., or relative to the workspace) or http(s) URLs of a skill file or a skill index. User config only.' },
|
|
100
|
+
caCertificates: { ...strings, description: 'PEM files of extra certificate authorities to trust (absolute or ~/...), for networks that re-sign TLS. Needs a window reload. User config only.' },
|
|
101
|
+
aliases: { type: 'object', description: 'Short names for models, for example "fast": "anthropic:claude-haiku-4-5".', additionalProperties: { type: 'string' } },
|
|
102
|
+
modeModels: { type: 'object', description: 'Model for a chat mode that has none of its own: mode id to model.', additionalProperties: { type: 'string' } },
|
|
103
|
+
sessionRetentionDays: { type: 'integer', minimum: 1, description: 'Delete saved chats not updated for this many days when the extension starts. Unset keeps everything. User config only.' },
|
|
104
|
+
display: {
|
|
105
|
+
type: 'object',
|
|
106
|
+
description: 'How blocks in the chat are shown.',
|
|
107
|
+
properties: {
|
|
108
|
+
blockDefault: { enum: ['collapsed', 'expanded'] },
|
|
109
|
+
detail: { enum: ['compact', 'full'] },
|
|
110
|
+
showReasoning: { type: 'boolean' },
|
|
111
|
+
blocks: {
|
|
112
|
+
type: 'object',
|
|
113
|
+
description: 'Per kind of block: reasoning, terminal (command output), edit (file edits), mcp (MCP tool results).',
|
|
114
|
+
properties: {
|
|
115
|
+
reasoning: { enum: ['hidden', 'collapsed', 'expanded'] },
|
|
116
|
+
terminal: { enum: ['collapsed', 'expanded'] },
|
|
117
|
+
edit: { enum: ['collapsed', 'expanded'] },
|
|
118
|
+
mcp: { enum: ['collapsed', 'expanded'] },
|
|
119
|
+
},
|
|
120
|
+
additionalProperties: false,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
additionalProperties: false,
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
};
|
package/dist/config.js
CHANGED
|
@@ -125,7 +125,8 @@ export function fastDefaultFor(provider) {
|
|
|
125
125
|
case 'openrouter':
|
|
126
126
|
return 'openai/gpt-4o-mini';
|
|
127
127
|
case 'minimax':
|
|
128
|
-
|
|
128
|
+
// MiniMax-M2 was retired (error 2069). M3 answered a completion fastest in a live check.
|
|
129
|
+
return 'MiniMax-M3';
|
|
129
130
|
case 'bedrock':
|
|
130
131
|
return 'us.anthropic.claude-haiku-4-5-20251001-v1:0';
|
|
131
132
|
case 'vertex':
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import { generateText } from 'ai';
|
|
15
15
|
import { mediaPartLabel, mediaPartTokens } from '../attachments.js';
|
|
16
16
|
import { stripThinkTags } from '../agent/think-tags.js';
|
|
17
|
+
import { overrideContextTokens } from '../model-overrides.js';
|
|
17
18
|
import { createLanguageModel } from '../providers.js';
|
|
18
19
|
/**
|
|
19
20
|
* Approximate model context window (input) in tokens. Used to decide when
|
|
@@ -84,6 +85,9 @@ const WINDOW_SIZES = {
|
|
|
84
85
|
'minimax-m2': 204_800,
|
|
85
86
|
};
|
|
86
87
|
export function getModelWindowTokens(model) {
|
|
88
|
+
const overridden = overrideContextTokens(model);
|
|
89
|
+
if (overridden)
|
|
90
|
+
return overridden;
|
|
87
91
|
const id = typeof model === 'string' ? model : model.model;
|
|
88
92
|
const stripped = id.toLowerCase().replace(/^models\//, '');
|
|
89
93
|
// Direct hit first.
|
package/dist/context/mask.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Results that say what a change did are kept: they are small and the model must not forget them. */
|
|
2
|
-
export const NEVER_MASK_TOOLS = new Set(['write_file', 'edit_file', 'edit_notebook', 'run_command', 'sub_agent']);
|
|
2
|
+
export const NEVER_MASK_TOOLS = new Set(['write_file', 'edit_file', 'edit_notebook', 'apply_patch', 'run_command', 'sub_agent']);
|
|
3
3
|
const STUB_MARK = 'result not shown to save context';
|
|
4
4
|
/** Index of the first message of the last `keepRecentTurns` assistant turns (0 when there are not that many). */
|
|
5
5
|
export function maskBoundary(messages, keepRecentTurns) {
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Named providers beyond the built-in eleven: a table of well-known OpenAI-compatible services plus whatever the
|
|
3
|
+
* user defines under `customProviders` in `~/.forge/config.json`. A model on one of them is written `id:model`
|
|
4
|
+
* (e.g. `groq:llama-3.3-70b-versatile`) and resolves to an endpoint (base URL, key, headers) that
|
|
5
|
+
* `createLanguageModel` calls with the OpenAI chat or Anthropic message style. Pure; nothing here reads files.
|
|
6
|
+
*/
|
|
7
|
+
export type EndpointApi = 'openai-compatible' | 'anthropic';
|
|
8
|
+
export interface CustomModelConfig {
|
|
9
|
+
/** The id sent to the API when the key used in Forge differs from it. */
|
|
10
|
+
id?: string;
|
|
11
|
+
name?: string;
|
|
12
|
+
limit?: {
|
|
13
|
+
context?: number;
|
|
14
|
+
output?: number;
|
|
15
|
+
};
|
|
16
|
+
cost?: {
|
|
17
|
+
input?: number;
|
|
18
|
+
output?: number;
|
|
19
|
+
};
|
|
20
|
+
toolCall?: boolean;
|
|
21
|
+
reasoning?: boolean;
|
|
22
|
+
modalities?: {
|
|
23
|
+
input: string[];
|
|
24
|
+
output: string[];
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export interface CustomProviderConfig {
|
|
28
|
+
name?: string;
|
|
29
|
+
baseUrl?: string;
|
|
30
|
+
/** Stored as plain text in the config file; prefer `apiKeyEnv`. */
|
|
31
|
+
apiKey?: string;
|
|
32
|
+
/** Name of the environment variable that holds the key. */
|
|
33
|
+
apiKeyEnv?: string;
|
|
34
|
+
headers?: Record<string, string>;
|
|
35
|
+
api?: EndpointApi;
|
|
36
|
+
/** Give up on a request that has not answered after this many milliseconds. */
|
|
37
|
+
timeoutMs?: number;
|
|
38
|
+
/** Abort a streamed answer that stays silent this long. */
|
|
39
|
+
chunkTimeoutMs?: number;
|
|
40
|
+
models?: Record<string, CustomModelConfig>;
|
|
41
|
+
whitelist?: string[];
|
|
42
|
+
blacklist?: string[];
|
|
43
|
+
}
|
|
44
|
+
/** Where a call goes: the resolved form of a provider, carried on `ModelConfig.endpoint`. */
|
|
45
|
+
export interface ProviderEndpoint {
|
|
46
|
+
id: string;
|
|
47
|
+
name: string;
|
|
48
|
+
baseUrl: string;
|
|
49
|
+
apiKey?: string;
|
|
50
|
+
headers?: Record<string, string>;
|
|
51
|
+
api: EndpointApi;
|
|
52
|
+
timeoutMs?: number;
|
|
53
|
+
chunkTimeoutMs?: number;
|
|
54
|
+
}
|
|
55
|
+
export interface ProviderPreset {
|
|
56
|
+
name: string;
|
|
57
|
+
baseUrl: string;
|
|
58
|
+
apiKeyEnv: string;
|
|
59
|
+
api?: EndpointApi;
|
|
60
|
+
}
|
|
61
|
+
/** Defaults for services that speak the OpenAI chat protocol. Any field can be overridden under `customProviders`. */
|
|
62
|
+
export declare const PROVIDER_PRESETS: Readonly<Record<string, ProviderPreset>>;
|
|
63
|
+
/** Why an entry of `customProviders` cannot be used, one problem per bad entry. A preset id may omit its URL. */
|
|
64
|
+
export declare function customProviderProblems(custom: Record<string, CustomProviderConfig> | undefined): Array<{
|
|
65
|
+
id: string;
|
|
66
|
+
message: string;
|
|
67
|
+
}>;
|
|
68
|
+
/**
|
|
69
|
+
* The `customProviders` of the running host, so every place that turns a model name into a model (aliases,
|
|
70
|
+
* the cheap model, sub-agents, the picker) sees them without each call site passing the config along.
|
|
71
|
+
* Hosts register at the start of every run; tests reset with `undefined`.
|
|
72
|
+
*/
|
|
73
|
+
export declare function registerCustomProviders(custom: Record<string, CustomProviderConfig> | undefined): void;
|
|
74
|
+
export declare function registeredCustomProviders(): Record<string, CustomProviderConfig> | undefined;
|
|
75
|
+
export interface ModelFilter {
|
|
76
|
+
whitelist?: string[];
|
|
77
|
+
blacklist?: string[];
|
|
78
|
+
}
|
|
79
|
+
/** `modelFilters` of the running host (per provider id), read by the model pickers. */
|
|
80
|
+
export declare function registerModelFilters(filters: Record<string, ModelFilter> | undefined): void;
|
|
81
|
+
/** The filter for a provider id: the registered `modelFilters` entry, else the whitelist/blacklist on its custom provider. */
|
|
82
|
+
export declare function modelFilterFor(providerId: string): ModelFilter | undefined;
|
|
83
|
+
/** Preset ids and custom ids, once each; a built-in id never appears. */
|
|
84
|
+
export declare function knownProviderIds(custom: Record<string, CustomProviderConfig> | undefined): string[];
|
|
85
|
+
/** The endpoint for a provider id, or undefined when the id is built-in, unknown, or has no usable URL. */
|
|
86
|
+
export declare function resolveProviderEndpoint(id: string, custom: Record<string, CustomProviderConfig> | undefined, env?: NodeJS.ProcessEnv): ProviderEndpoint | undefined;
|
|
87
|
+
/** The id the API expects for a model key (`models.<key>.id`), or the key itself. */
|
|
88
|
+
export declare function apiModelId(providerId: string, modelKey: string, custom: Record<string, CustomProviderConfig> | undefined): string;
|
|
89
|
+
/** Apply a provider's `whitelist` (only these) then `blacklist` (not these) to a model list. */
|
|
90
|
+
export declare function filterModels<T extends {
|
|
91
|
+
id: string;
|
|
92
|
+
}>(entries: readonly T[], filter: {
|
|
93
|
+
whitelist?: string[];
|
|
94
|
+
blacklist?: string[];
|
|
95
|
+
} | undefined): T[];
|