substrate-ai 0.2.28 → 0.2.30
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/dist/{errors-CswS7Mzg.js → adapter-registry-PsWhP_1Q.js} +2 -111
- package/dist/cli/index.js +30 -333
- package/dist/config-migrator-DSi8KhQC.js +244 -0
- package/dist/{experimenter-bc40oi8p.js → experimenter-f_Y1rreV.js} +1 -1
- package/dist/{helpers-DljGJnFF.js → helpers-RL22dYtn.js} +111 -2
- package/dist/index.js +2 -2
- package/dist/{run-BCyrbL3w.js → run-Ajt187oE.js} +451 -93
- package/dist/run-KBcR3Jpi.js +8 -0
- package/dist/{upgrade-DzpjKYlD.js → upgrade-CImByfkk.js} +3 -2
- package/dist/{upgrade-CJ0JFQ2c.js → upgrade-Cvwtnwl4.js} +2 -2
- package/dist/{version-manager-impl-CtzNu7YZ.js → version-manager-impl-CizNmmLT.js} +3 -242
- package/dist/version-manager-impl-aL5IemIm.js +4 -0
- package/package.json +1 -1
- package/packs/bmad/prompts/fix-story.md +5 -0
- package/dist/run-CIgIYtKf.js +0 -7
- package/dist/version-manager-impl-BDfiGXWX.js +0 -3
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/modules/config/config-schema.ts
|
|
5
|
+
/** Subscription routing modes */
|
|
6
|
+
const SubscriptionRoutingSchema = z.enum([
|
|
7
|
+
"auto",
|
|
8
|
+
"subscription",
|
|
9
|
+
"api",
|
|
10
|
+
"disabled"
|
|
11
|
+
]);
|
|
12
|
+
/** Rate limit configuration for a provider */
|
|
13
|
+
const RateLimitSchema = z.object({
|
|
14
|
+
tokens: z.number().int().positive(),
|
|
15
|
+
window_seconds: z.number().int().positive()
|
|
16
|
+
}).strict();
|
|
17
|
+
/** Per-provider configuration */
|
|
18
|
+
const ProviderConfigSchema = z.object({
|
|
19
|
+
enabled: z.boolean(),
|
|
20
|
+
cli_path: z.string().optional(),
|
|
21
|
+
subscription_routing: SubscriptionRoutingSchema,
|
|
22
|
+
max_concurrent: z.number().int().min(1).max(32),
|
|
23
|
+
rate_limit: RateLimitSchema.optional(),
|
|
24
|
+
api_key_env: z.string().optional(),
|
|
25
|
+
api_billing: z.boolean()
|
|
26
|
+
}).strict();
|
|
27
|
+
/** Map of all known providers */
|
|
28
|
+
const ProvidersSchema = z.object({
|
|
29
|
+
claude: ProviderConfigSchema.optional(),
|
|
30
|
+
codex: ProviderConfigSchema.optional(),
|
|
31
|
+
gemini: ProviderConfigSchema.optional()
|
|
32
|
+
}).strict();
|
|
33
|
+
const LogLevelSchema = z.enum([
|
|
34
|
+
"trace",
|
|
35
|
+
"debug",
|
|
36
|
+
"info",
|
|
37
|
+
"warn",
|
|
38
|
+
"error",
|
|
39
|
+
"fatal"
|
|
40
|
+
]);
|
|
41
|
+
const GlobalSettingsSchema = z.object({
|
|
42
|
+
log_level: LogLevelSchema,
|
|
43
|
+
max_concurrent_tasks: z.number().int().min(1).max(64),
|
|
44
|
+
budget_cap_tokens: z.number().int().min(0),
|
|
45
|
+
budget_cap_usd: z.number().min(0),
|
|
46
|
+
workspace_dir: z.string().optional(),
|
|
47
|
+
update_check: z.boolean().optional()
|
|
48
|
+
}).strict();
|
|
49
|
+
const CostTrackerConfigSchema = z.object({
|
|
50
|
+
enabled: z.boolean(),
|
|
51
|
+
token_rates_provider: z.enum(["builtin", "custom"]),
|
|
52
|
+
track_planning_costs: z.boolean(),
|
|
53
|
+
savings_reporting: z.boolean()
|
|
54
|
+
}).strict();
|
|
55
|
+
const BudgetConfigSchema = z.object({
|
|
56
|
+
default_task_budget_usd: z.number().min(0),
|
|
57
|
+
default_session_budget_usd: z.number().min(0),
|
|
58
|
+
planning_costs_count_against_budget: z.boolean(),
|
|
59
|
+
warning_threshold_percent: z.number().min(0).max(100)
|
|
60
|
+
}).strict();
|
|
61
|
+
const RoutingRuleSchema = z.object({
|
|
62
|
+
task_type: z.string(),
|
|
63
|
+
preferred_provider: z.string(),
|
|
64
|
+
fallback_providers: z.array(z.string())
|
|
65
|
+
}).strict();
|
|
66
|
+
const RoutingPolicySchema = z.object({
|
|
67
|
+
default_provider: z.string(),
|
|
68
|
+
rules: z.array(RoutingRuleSchema)
|
|
69
|
+
}).strict();
|
|
70
|
+
/**
|
|
71
|
+
* Per-workflow token ceiling overrides.
|
|
72
|
+
* Keys match the workflow type names used in prompts and events.
|
|
73
|
+
* Values must be positive integers.
|
|
74
|
+
*/
|
|
75
|
+
const TokenCeilingsSchema = z.object({
|
|
76
|
+
"create-story": z.number().int().positive("create-story token ceiling must be a positive integer").optional(),
|
|
77
|
+
"dev-story": z.number().int().positive("dev-story token ceiling must be a positive integer").optional(),
|
|
78
|
+
"code-review": z.number().int().positive("code-review token ceiling must be a positive integer").optional(),
|
|
79
|
+
"test-plan": z.number().int().positive("test-plan token ceiling must be a positive integer").optional(),
|
|
80
|
+
"test-expansion": z.number().int().positive("test-expansion token ceiling must be a positive integer").optional()
|
|
81
|
+
});
|
|
82
|
+
/** Current supported config format version */
|
|
83
|
+
const CURRENT_CONFIG_FORMAT_VERSION = "1";
|
|
84
|
+
/** Current supported task graph version */
|
|
85
|
+
const CURRENT_TASK_GRAPH_VERSION = "1";
|
|
86
|
+
/** All config format versions this toolkit can read and validate */
|
|
87
|
+
const SUPPORTED_CONFIG_FORMAT_VERSIONS = ["1"];
|
|
88
|
+
/** All task graph format versions this toolkit can read and validate */
|
|
89
|
+
const SUPPORTED_TASK_GRAPH_VERSIONS = ["1"];
|
|
90
|
+
const SubstrateConfigSchema = z.object({
|
|
91
|
+
config_format_version: z.enum(["1"]),
|
|
92
|
+
task_graph_version: z.enum(["1"]).optional(),
|
|
93
|
+
global: GlobalSettingsSchema,
|
|
94
|
+
providers: ProvidersSchema,
|
|
95
|
+
cost_tracker: CostTrackerConfigSchema.optional(),
|
|
96
|
+
budget: BudgetConfigSchema.optional(),
|
|
97
|
+
token_ceilings: TokenCeilingsSchema.optional()
|
|
98
|
+
}).strict();
|
|
99
|
+
const PartialProviderConfigSchema = ProviderConfigSchema.partial();
|
|
100
|
+
const PartialGlobalSettingsSchema = GlobalSettingsSchema.partial();
|
|
101
|
+
const PartialSubstrateConfigSchema = z.object({
|
|
102
|
+
config_format_version: z.enum(["1"]).optional(),
|
|
103
|
+
task_graph_version: z.enum(["1"]).optional(),
|
|
104
|
+
global: PartialGlobalSettingsSchema.optional(),
|
|
105
|
+
providers: z.object({
|
|
106
|
+
claude: PartialProviderConfigSchema.optional(),
|
|
107
|
+
codex: PartialProviderConfigSchema.optional(),
|
|
108
|
+
gemini: PartialProviderConfigSchema.optional()
|
|
109
|
+
}).partial().optional(),
|
|
110
|
+
cost_tracker: CostTrackerConfigSchema.partial().optional(),
|
|
111
|
+
budget: BudgetConfigSchema.partial().optional(),
|
|
112
|
+
token_ceilings: TokenCeilingsSchema.optional()
|
|
113
|
+
}).strict();
|
|
114
|
+
|
|
115
|
+
//#endregion
|
|
116
|
+
//#region src/modules/config/config-migrator.ts
|
|
117
|
+
/**
|
|
118
|
+
* ConfigMigrator manages a registry of migration functions and applies them
|
|
119
|
+
* sequentially to upgrade config documents from one format version to another.
|
|
120
|
+
*/
|
|
121
|
+
var ConfigMigrator = class {
|
|
122
|
+
migrations = new Map();
|
|
123
|
+
/**
|
|
124
|
+
* Register a migration function for the given version key.
|
|
125
|
+
*
|
|
126
|
+
* @param key - Migration key in format "N->M" (e.g. "1->2")
|
|
127
|
+
* @param fn - Migration function that receives the raw config and returns the migrated config
|
|
128
|
+
*/
|
|
129
|
+
register(key, fn) {
|
|
130
|
+
this.migrations.set(key, fn);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Check whether a sequential migration path exists from fromVersion to toVersion.
|
|
134
|
+
*
|
|
135
|
+
* @param fromVersion - Starting version string
|
|
136
|
+
* @param toVersion - Target version string
|
|
137
|
+
* @returns true if every step in the path is registered
|
|
138
|
+
*/
|
|
139
|
+
canMigrate(fromVersion, toVersion) {
|
|
140
|
+
if (fromVersion === toVersion) return true;
|
|
141
|
+
const from = parseInt(fromVersion, 10);
|
|
142
|
+
const to = parseInt(toVersion, 10);
|
|
143
|
+
if (isNaN(from) || isNaN(to) || from >= to) return false;
|
|
144
|
+
for (let v = from; v < to; v++) {
|
|
145
|
+
const key = `${String(v)}->${String(v + 1)}`;
|
|
146
|
+
if (!this.migrations.has(key)) return false;
|
|
147
|
+
}
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Apply sequential migrations from fromVersion to toVersion.
|
|
152
|
+
*
|
|
153
|
+
* If fromVersion === toVersion, returns a no-op success result.
|
|
154
|
+
* If any intermediate migration is missing, returns success:false.
|
|
155
|
+
*
|
|
156
|
+
* When filePath is provided and migration is needed, a backup is written to
|
|
157
|
+
* `${filePath}.bak.v${fromVersion}` before any transformations are applied.
|
|
158
|
+
*
|
|
159
|
+
* @param config - Raw config object to migrate
|
|
160
|
+
* @param fromVersion - Starting format version string
|
|
161
|
+
* @param toVersion - Target format version string
|
|
162
|
+
* @param filePath - Optional path to the source config file for backup creation
|
|
163
|
+
* @returns Object containing the (possibly migrated) config and a MigrationResult
|
|
164
|
+
*/
|
|
165
|
+
migrate(config, fromVersion, toVersion, filePath) {
|
|
166
|
+
if (fromVersion === toVersion) return {
|
|
167
|
+
config,
|
|
168
|
+
result: {
|
|
169
|
+
success: true,
|
|
170
|
+
fromVersion,
|
|
171
|
+
toVersion,
|
|
172
|
+
migratedKeys: [],
|
|
173
|
+
manualStepsRequired: [],
|
|
174
|
+
backupPath: null
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
const from = parseInt(fromVersion, 10);
|
|
178
|
+
const to = parseInt(toVersion, 10);
|
|
179
|
+
if (isNaN(from) || isNaN(to) || from >= to) return {
|
|
180
|
+
config,
|
|
181
|
+
result: {
|
|
182
|
+
success: false,
|
|
183
|
+
fromVersion,
|
|
184
|
+
toVersion,
|
|
185
|
+
migratedKeys: [],
|
|
186
|
+
manualStepsRequired: [`Cannot migrate from version "${fromVersion}" to "${toVersion}": invalid version range.`],
|
|
187
|
+
backupPath: null
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
for (let v = from; v < to; v++) {
|
|
191
|
+
const key = `${String(v)}->${String(v + 1)}`;
|
|
192
|
+
if (!this.migrations.has(key)) return {
|
|
193
|
+
config,
|
|
194
|
+
result: {
|
|
195
|
+
success: false,
|
|
196
|
+
fromVersion,
|
|
197
|
+
toVersion,
|
|
198
|
+
migratedKeys: [],
|
|
199
|
+
manualStepsRequired: [`Missing migration step: "${key}". Cannot automatically migrate from version "${fromVersion}" to "${toVersion}". Please upgrade the toolkit: npm install -g substrate@latest`],
|
|
200
|
+
backupPath: null
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
let backupPath = null;
|
|
205
|
+
if (filePath !== void 0) {
|
|
206
|
+
backupPath = `${filePath}.bak.v${fromVersion}`;
|
|
207
|
+
const originalContent = readFileSync(filePath, "utf-8");
|
|
208
|
+
writeFileSync(backupPath, originalContent, "utf-8");
|
|
209
|
+
}
|
|
210
|
+
let current = config;
|
|
211
|
+
const migratedKeys = [];
|
|
212
|
+
for (let v = from; v < to; v++) {
|
|
213
|
+
const key = `${String(v)}->${String(v + 1)}`;
|
|
214
|
+
const fn = this.migrations.get(key);
|
|
215
|
+
const before = JSON.stringify(current);
|
|
216
|
+
current = fn(current);
|
|
217
|
+
const after = JSON.stringify(current);
|
|
218
|
+
if (current !== null && typeof current === "object" && !Array.isArray(current)) {
|
|
219
|
+
const beforeObj = JSON.parse(before);
|
|
220
|
+
const afterObj = JSON.parse(after);
|
|
221
|
+
for (const k of Object.keys(afterObj)) if (JSON.stringify(afterObj[k]) !== JSON.stringify(beforeObj[k])) {
|
|
222
|
+
if (!migratedKeys.includes(k)) migratedKeys.push(k);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
config: current,
|
|
228
|
+
result: {
|
|
229
|
+
success: true,
|
|
230
|
+
fromVersion,
|
|
231
|
+
toVersion,
|
|
232
|
+
migratedKeys,
|
|
233
|
+
manualStepsRequired: [],
|
|
234
|
+
backupPath
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
/** Singleton instance for use throughout the toolkit */
|
|
240
|
+
const defaultConfigMigrator = new ConfigMigrator();
|
|
241
|
+
|
|
242
|
+
//#endregion
|
|
243
|
+
export { CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, PartialSubstrateConfigSchema, SUPPORTED_CONFIG_FORMAT_VERSIONS, SUPPORTED_TASK_GRAPH_VERSIONS, SubstrateConfigSchema, defaultConfigMigrator };
|
|
244
|
+
//# sourceMappingURL=config-migrator-DSi8KhQC.js.map
|
|
@@ -2,6 +2,115 @@ import * as readline from "node:readline";
|
|
|
2
2
|
import { EventEmitter } from "node:events";
|
|
3
3
|
import { randomUUID } from "crypto";
|
|
4
4
|
|
|
5
|
+
//#region src/core/errors.ts
|
|
6
|
+
/**
|
|
7
|
+
* Error definitions for Substrate
|
|
8
|
+
* Provides structured error hierarchy for all toolkit operations
|
|
9
|
+
*/
|
|
10
|
+
/** Base error class for all Substrate errors */
|
|
11
|
+
var AdtError = class AdtError extends Error {
|
|
12
|
+
code;
|
|
13
|
+
context;
|
|
14
|
+
constructor(message, code, context = {}) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = "AdtError";
|
|
17
|
+
this.code = code;
|
|
18
|
+
this.context = context;
|
|
19
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, AdtError);
|
|
20
|
+
}
|
|
21
|
+
toJSON() {
|
|
22
|
+
return {
|
|
23
|
+
name: this.name,
|
|
24
|
+
message: this.message,
|
|
25
|
+
code: this.code,
|
|
26
|
+
context: this.context,
|
|
27
|
+
stack: this.stack
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
/** Error thrown when task configuration is invalid */
|
|
32
|
+
var TaskConfigError = class extends AdtError {
|
|
33
|
+
constructor(message, context = {}) {
|
|
34
|
+
super(message, "TASK_CONFIG_ERROR", context);
|
|
35
|
+
this.name = "TaskConfigError";
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
/** Error thrown when a worker/agent operation fails */
|
|
39
|
+
var WorkerError = class extends AdtError {
|
|
40
|
+
constructor(message, context = {}) {
|
|
41
|
+
super(message, "WORKER_ERROR", context);
|
|
42
|
+
this.name = "WorkerError";
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
/** Error thrown when a worker/agent cannot be found */
|
|
46
|
+
var WorkerNotFoundError = class extends AdtError {
|
|
47
|
+
constructor(agentId) {
|
|
48
|
+
super(`Worker agent not found: ${agentId}`, "WORKER_NOT_FOUND", { agentId });
|
|
49
|
+
this.name = "WorkerNotFoundError";
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
/** Error thrown when a task graph is invalid */
|
|
53
|
+
var TaskGraphError = class extends AdtError {
|
|
54
|
+
constructor(message, context = {}) {
|
|
55
|
+
super(message, "TASK_GRAPH_ERROR", context);
|
|
56
|
+
this.name = "TaskGraphError";
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
/** Error thrown when a task graph has cycles (deadlock) */
|
|
60
|
+
var TaskGraphCycleError = class extends TaskGraphError {
|
|
61
|
+
constructor(cycle) {
|
|
62
|
+
super(`Circular dependency detected in task graph: ${cycle.join(" -> ")}`, { cycle });
|
|
63
|
+
this.name = "TaskGraphCycleError";
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
/** Error thrown when a budget limit is exceeded */
|
|
67
|
+
var BudgetExceededError = class extends AdtError {
|
|
68
|
+
constructor(limit, current, context = {}) {
|
|
69
|
+
super(`Budget cap exceeded: current=${String(current)}, limit=${String(limit)}`, "BUDGET_EXCEEDED", {
|
|
70
|
+
limit,
|
|
71
|
+
current,
|
|
72
|
+
...context
|
|
73
|
+
});
|
|
74
|
+
this.name = "BudgetExceededError";
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
/** Error thrown when git operations fail */
|
|
78
|
+
var GitError = class extends AdtError {
|
|
79
|
+
constructor(message, context = {}) {
|
|
80
|
+
super(message, "GIT_ERROR", context);
|
|
81
|
+
this.name = "GitError";
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
/** Error thrown when configuration is invalid or missing */
|
|
85
|
+
var ConfigError = class extends AdtError {
|
|
86
|
+
constructor(message, context = {}) {
|
|
87
|
+
super(message, "CONFIG_ERROR", context);
|
|
88
|
+
this.name = "ConfigError";
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
/** Error thrown when state recovery fails */
|
|
92
|
+
var RecoveryError = class extends AdtError {
|
|
93
|
+
constructor(message, context = {}) {
|
|
94
|
+
super(message, "RECOVERY_ERROR", context);
|
|
95
|
+
this.name = "RecoveryError";
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
/** Error thrown when a config file uses an incompatible format version */
|
|
99
|
+
var ConfigIncompatibleFormatError = class extends AdtError {
|
|
100
|
+
constructor(message, context = {}) {
|
|
101
|
+
super(message, "CONFIG_INCOMPATIBLE_FORMAT", context);
|
|
102
|
+
this.name = "ConfigIncompatibleFormatError";
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
/** Error thrown when a task graph file uses an incompatible format version */
|
|
106
|
+
var TaskGraphIncompatibleFormatError = class extends AdtError {
|
|
107
|
+
constructor(message, context = {}) {
|
|
108
|
+
super(message, "TASK_GRAPH_INCOMPATIBLE_FORMAT", context);
|
|
109
|
+
this.name = "TaskGraphIncompatibleFormatError";
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
//#endregion
|
|
5
114
|
//#region src/tui/ansi.ts
|
|
6
115
|
/**
|
|
7
116
|
* ANSI escape code helpers for TUI rendering.
|
|
@@ -807,5 +916,5 @@ async function withRetry(fn, maxRetries = 3, baseDelayMs = 100) {
|
|
|
807
916
|
}
|
|
808
917
|
|
|
809
918
|
//#endregion
|
|
810
|
-
export { assertDefined, createEventBus, createTuiApp, deepClone, formatDuration, generateId, isPlainObject, isTuiCapable, printNonTtyWarning, sleep, withRetry };
|
|
811
|
-
//# sourceMappingURL=helpers-
|
|
919
|
+
export { AdtError, BudgetExceededError, ConfigError, ConfigIncompatibleFormatError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError, assertDefined, createEventBus, createTuiApp, deepClone, formatDuration, generateId, isPlainObject, isTuiCapable, printNonTtyWarning, sleep, withRetry };
|
|
920
|
+
//# sourceMappingURL=helpers-RL22dYtn.js.map
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { childLogger, createLogger, logger } from "./logger-D2fS2ccL.js";
|
|
2
|
-
import { AdapterRegistry,
|
|
3
|
-
import { assertDefined, createEventBus, createTuiApp, deepClone, formatDuration, generateId, isPlainObject, isTuiCapable, printNonTtyWarning, sleep, withRetry } from "./helpers-
|
|
2
|
+
import { AdapterRegistry, ClaudeCodeAdapter, CodexCLIAdapter, GeminiCLIAdapter } from "./adapter-registry-PsWhP_1Q.js";
|
|
3
|
+
import { AdtError, BudgetExceededError, ConfigError, ConfigIncompatibleFormatError, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError, assertDefined, createEventBus, createTuiApp, deepClone, formatDuration, generateId, isPlainObject, isTuiCapable, printNonTtyWarning, sleep, withRetry } from "./helpers-RL22dYtn.js";
|
|
4
4
|
|
|
5
5
|
//#region src/core/di.ts
|
|
6
6
|
/**
|