@defai.digital/automatosx 6.5.10 β 6.5.11
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/CHANGELOG.md +76 -0
- package/README.md +39 -0
- package/dist/index.js +200 -44
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,82 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [6.5.11] - 2025-11-01
|
|
6
|
+
|
|
7
|
+
### π Bug Fixes
|
|
8
|
+
|
|
9
|
+
#### Fallback Provider & Code Quality Improvements
|
|
10
|
+
|
|
11
|
+
**Critical Fixes:**
|
|
12
|
+
|
|
13
|
+
- **GitHub Issue #8**: Fallback provider now activates when primary provider fails
|
|
14
|
+
- Fixed `src/agents/executor.ts` to implement proper fallback logic during runtime
|
|
15
|
+
- Primary provider failures now trigger automatic fallback to configured `fallbackProvider`
|
|
16
|
+
- Handles authentication errors (401), rate limits (429, 503), timeouts, and all error types
|
|
17
|
+
- User notified in verbose mode when fallback is used
|
|
18
|
+
- Both errors logged when both providers fail
|
|
19
|
+
- See `automatosx/PRD/github-issue-8-fallback-provider-fix.md` for details
|
|
20
|
+
|
|
21
|
+
**Bug Fixes - Round 2:**
|
|
22
|
+
|
|
23
|
+
- **Bug #106** (CRITICAL): parseInt NaN validation in agent create (`src/cli/commands/agent/create.ts`)
|
|
24
|
+
- Added NaN validation to template/team selection parseInt() calls
|
|
25
|
+
- Graceful fallback to first option on invalid input
|
|
26
|
+
|
|
27
|
+
- **Bug #107** (HIGH): NaN propagation in PlanGenerator (`src/core/spec/PlanGenerator.ts`)
|
|
28
|
+
- Added NaN validation to `parseDuration()` and `parseMemoryLimit()` functions
|
|
29
|
+
- Prevents NaN from corrupting cost/duration estimates
|
|
30
|
+
|
|
31
|
+
- **Bug #108** (HIGH): Stream error handling in RouterTraceLogger (`src/core/router-trace-logger.ts`)
|
|
32
|
+
- Added error handler to WriteStream to prevent process crashes
|
|
33
|
+
- Added cleanup handlers for process exit signals (exit, SIGINT, SIGTERM)
|
|
34
|
+
|
|
35
|
+
- **Bug #109** (HIGH): Array access safety in Router (`src/core/router.ts`)
|
|
36
|
+
- Verified already safe with nullish coalescing operator
|
|
37
|
+
|
|
38
|
+
- **Bug #110** (HIGH): Array access in RoutingStrategy (`src/core/routing-strategy.ts`)
|
|
39
|
+
- Fixed 3 instances of unsafe array access with explicit bounds checks
|
|
40
|
+
- Replaced non-null assertions with proper null checks
|
|
41
|
+
|
|
42
|
+
**Bug Fixes - Round 3 (Deep Analysis):**
|
|
43
|
+
|
|
44
|
+
- **Bug #118** (CRITICAL): DB connection pool fileMustExist inverted logic (`src/core/db-connection-pool.ts`)
|
|
45
|
+
- Fixed inverted `fileMustExist` flag in `createConnection()`
|
|
46
|
+
- Write connections can now create new databases (fresh installs work)
|
|
47
|
+
- Read-only connections properly require existing database files
|
|
48
|
+
- Changed `fileMustExist: !readonly` to `fileMustExist: readonly`
|
|
49
|
+
|
|
50
|
+
- **Bug #119** (HIGH): TelemetryCollector close() race condition (`src/core/telemetry/TelemetryCollector.ts`)
|
|
51
|
+
- Fixed race condition where `this.closed = true` was set before `await this.flush()`
|
|
52
|
+
- Buffered telemetry events now persist on shutdown instead of being dropped
|
|
53
|
+
- Moved `this.closed = true` to after successful flush
|
|
54
|
+
|
|
55
|
+
- **Bug #120** (HIGH): MCP server initialization promise leak (`src/mcp/server.ts`)
|
|
56
|
+
- Fixed cached rejected promise in `initializationPromise`
|
|
57
|
+
- Server can now recover from initialization failures
|
|
58
|
+
- Added try/catch to clear `initializationPromise` on error
|
|
59
|
+
|
|
60
|
+
- **Bug #121** (MEDIUM): Division by zero in adaptive cache (`src/core/adaptive-cache.ts`)
|
|
61
|
+
- Fixed division by `avgInterval` when it equals zero
|
|
62
|
+
- Occurs when cache entries accessed at exact same timestamp
|
|
63
|
+
- Added zero-check before score calculation to prevent NaN
|
|
64
|
+
|
|
65
|
+
**Impact:**
|
|
66
|
+
- Multi-provider resilience now works as documented
|
|
67
|
+
- NaN validation prevents corrupted calculations
|
|
68
|
+
- Resource cleanup prevents memory leaks
|
|
69
|
+
- Database initialization works for fresh installs
|
|
70
|
+
- Telemetry data persists correctly on shutdown
|
|
71
|
+
- MCP server recovers from initialization failures
|
|
72
|
+
- Cache prediction algorithm handles edge cases
|
|
73
|
+
- All critical/high/medium severity bugs resolved
|
|
74
|
+
- See `automatosx/PRD/bug-fixes-round2-2025-11-01.md` for complete details
|
|
75
|
+
|
|
76
|
+
### π Documentation
|
|
77
|
+
|
|
78
|
+
- Updated version to v6.5.11 across all files
|
|
79
|
+
- Test suite: 2,612 passing tests β
|
|
80
|
+
|
|
5
81
|
## [6.5.9] - 2025-11-01
|
|
6
82
|
|
|
7
83
|
### β¨ Features
|
package/README.md
CHANGED
|
@@ -15,6 +15,8 @@ AutomatosX is the only AI CLI that combines declarative workflow specs, policy-d
|
|
|
15
15
|
|
|
16
16
|
**Status**: β
**Production Ready v6.5.6** | Nov 2025 | 20 Specialized Agents | Spec-Kit 100% Complete | Policy-Driven Routing | Auto-Generation
|
|
17
17
|
|
|
18
|
+
> β οΈ **Note on Cost Estimation (v6.5.11+)**: Cost estimation is **disabled by default** due to frequent pricing changes. The cost optimization features described below are still functional (routing, free-tier prioritization, policy constraints), but specific dollar amounts are not shown unless you enable cost estimation in `automatosx.config.json`. See [Cost Estimation Configuration](#cost-estimation-configuration) for details.
|
|
19
|
+
|
|
18
20
|
---
|
|
19
21
|
|
|
20
22
|
## π The Complete AI Workflow Platform
|
|
@@ -606,6 +608,8 @@ ax spec create "Build e-commerce checkout with Stripe, inventory, and fraud dete
|
|
|
606
608
|
|
|
607
609
|
## π° Policy-Driven Cost Optimization
|
|
608
610
|
|
|
611
|
+
> **Note**: Cost estimation is disabled by default (v6.5.11+). The routing and optimization features work the same, but cost estimates are not shown. See [Cost Estimation Configuration](#cost-estimation-configuration) to enable.
|
|
612
|
+
|
|
609
613
|
AutomatosX is the **only AI platform with built-in cost optimization**. Define your budget and constraintsβAutomatosX automatically routes every request to the optimal provider.
|
|
610
614
|
|
|
611
615
|
### How It Works
|
|
@@ -827,6 +831,41 @@ Each agent is an expert in their domain:
|
|
|
827
831
|
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
828
832
|
```
|
|
829
833
|
|
|
834
|
+
### Cost Estimation Configuration
|
|
835
|
+
|
|
836
|
+
**As of v6.5.11**, cost estimation is **disabled by default** because users reported that pricing changes frequently, making estimates unreliable.
|
|
837
|
+
|
|
838
|
+
#### How to Enable Cost Estimation
|
|
839
|
+
|
|
840
|
+
Edit `automatosx.config.json`:
|
|
841
|
+
|
|
842
|
+
```json
|
|
843
|
+
{
|
|
844
|
+
"costEstimation": {
|
|
845
|
+
"enabled": true, // Enable cost estimation
|
|
846
|
+
"disclaimer": "Cost estimates are approximate and may be outdated."
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
#### When Disabled (Default)
|
|
852
|
+
|
|
853
|
+
- β
Policy-driven routing **still works** (selects optimal provider)
|
|
854
|
+
- β
Free-tier prioritization **still works** (uses Gemini free tier)
|
|
855
|
+
- β
Provider selection **still works** (based on latency, reliability, privacy)
|
|
856
|
+
- β Cost estimates show "N/A" in CLI output
|
|
857
|
+
- β Cost constraints in specs are skipped (always pass)
|
|
858
|
+
|
|
859
|
+
#### When Enabled
|
|
860
|
+
|
|
861
|
+
- β
Cost estimates shown in `ax gen plan`, `ax providers info`, `ax providers trace`
|
|
862
|
+
- β
Cost constraints enforced (maxPerRequest, maxDaily)
|
|
863
|
+
- β οΈ Pricing data from Oct 2024 (may be outdated)
|
|
864
|
+
- β οΈ Verify current pricing on provider websites:
|
|
865
|
+
- [OpenAI Pricing](https://openai.com/pricing)
|
|
866
|
+
- [Gemini Pricing](https://ai.google.dev/pricing)
|
|
867
|
+
- [Claude Pricing](https://anthropic.com/pricing)
|
|
868
|
+
|
|
830
869
|
---
|
|
831
870
|
|
|
832
871
|
## π Real-World Examples
|
package/dist/index.js
CHANGED
|
@@ -2519,12 +2519,12 @@ var init_TelemetryCollector = __esm({
|
|
|
2519
2519
|
if (this.closed) {
|
|
2520
2520
|
return;
|
|
2521
2521
|
}
|
|
2522
|
-
this.closed = true;
|
|
2523
2522
|
if (this.flushInterval) {
|
|
2524
2523
|
clearInterval(this.flushInterval);
|
|
2525
2524
|
this.flushInterval = void 0;
|
|
2526
2525
|
}
|
|
2527
2526
|
await this.flush();
|
|
2527
|
+
this.closed = true;
|
|
2528
2528
|
if (this.db) {
|
|
2529
2529
|
try {
|
|
2530
2530
|
this.db.close();
|
|
@@ -9021,6 +9021,10 @@ var PRECOMPILED_CONFIG = {
|
|
|
9021
9021
|
"enableFreeTierPrioritization": true,
|
|
9022
9022
|
"enableWorkloadAwareRouting": true
|
|
9023
9023
|
},
|
|
9024
|
+
"costEstimation": {
|
|
9025
|
+
"enabled": false,
|
|
9026
|
+
"disclaimer": "Cost estimates are approximate and may be outdated. Visit provider pricing pages for current rates."
|
|
9027
|
+
},
|
|
9024
9028
|
"version": "6.5.9"
|
|
9025
9029
|
};
|
|
9026
9030
|
|
|
@@ -12286,6 +12290,9 @@ var RoutingStrategyManager = class extends EventEmitter {
|
|
|
12286
12290
|
return null;
|
|
12287
12291
|
}
|
|
12288
12292
|
const best = scores[0];
|
|
12293
|
+
if (!best) {
|
|
12294
|
+
return null;
|
|
12295
|
+
}
|
|
12289
12296
|
const reason = this.generateReason(best, scores);
|
|
12290
12297
|
const decision = {
|
|
12291
12298
|
selectedProvider: best.provider,
|
|
@@ -12786,7 +12793,7 @@ var PolicyEvaluator = class {
|
|
|
12786
12793
|
}
|
|
12787
12794
|
const scores = this.scoreProviders(filterResult.passed, policy);
|
|
12788
12795
|
const selected = scores[0]?.provider || null;
|
|
12789
|
-
if (selected && scores[0]) {
|
|
12796
|
+
if (selected && scores[0] && typeof scores[0].totalScore === "number") {
|
|
12790
12797
|
logger.info("Provider selected by policy", {
|
|
12791
12798
|
provider: selected,
|
|
12792
12799
|
score: scores[0].totalScore.toFixed(3),
|
|
@@ -12799,6 +12806,11 @@ var PolicyEvaluator = class {
|
|
|
12799
12806
|
* Check cost constraint
|
|
12800
12807
|
*/
|
|
12801
12808
|
async checkCostConstraint(provider, constraint) {
|
|
12809
|
+
const costEstimationEnabled = PRECOMPILED_CONFIG.costEstimation?.enabled ?? false;
|
|
12810
|
+
if (!costEstimationEnabled) {
|
|
12811
|
+
logger.debug("Cost estimation disabled, skipping cost constraints");
|
|
12812
|
+
return { passed: true, reason: "" };
|
|
12813
|
+
}
|
|
12802
12814
|
if (constraint.maxDaily && this.costTracker) {
|
|
12803
12815
|
const now = Date.now();
|
|
12804
12816
|
const dayAgo = now - 24 * 60 * 60 * 1e3;
|
|
@@ -12888,6 +12900,10 @@ var PolicyEvaluator = class {
|
|
|
12888
12900
|
* Lower cost = higher score
|
|
12889
12901
|
*/
|
|
12890
12902
|
calculateCostScore(metadata) {
|
|
12903
|
+
const costEstimationEnabled = PRECOMPILED_CONFIG.costEstimation?.enabled ?? false;
|
|
12904
|
+
if (!costEstimationEnabled) {
|
|
12905
|
+
return 0.5;
|
|
12906
|
+
}
|
|
12891
12907
|
const avgCost = (metadata.costPerToken.input + metadata.costPerToken.output) / 2;
|
|
12892
12908
|
const maxCost = 0.015;
|
|
12893
12909
|
const score = Math.max(0, 1 - avgCost / maxCost);
|
|
@@ -12913,6 +12929,10 @@ var PolicyEvaluator = class {
|
|
|
12913
12929
|
* Estimate request cost before execution
|
|
12914
12930
|
*/
|
|
12915
12931
|
estimateRequestCost(provider, inputTokens, outputTokens) {
|
|
12932
|
+
const costEstimationEnabled = PRECOMPILED_CONFIG.costEstimation?.enabled ?? false;
|
|
12933
|
+
if (!costEstimationEnabled) {
|
|
12934
|
+
return 0;
|
|
12935
|
+
}
|
|
12916
12936
|
const metadata = this.metadataRegistry[provider];
|
|
12917
12937
|
if (!metadata) return 0;
|
|
12918
12938
|
const cost = inputTokens / 1e3 * metadata.costPerToken.input + outputTokens / 1e3 * metadata.costPerToken.output;
|
|
@@ -12922,6 +12942,10 @@ var PolicyEvaluator = class {
|
|
|
12922
12942
|
* Check if request would exceed budget
|
|
12923
12943
|
*/
|
|
12924
12944
|
async wouldExceedBudget(provider, estimatedCost, constraint) {
|
|
12945
|
+
const costEstimationEnabled = PRECOMPILED_CONFIG.costEstimation?.enabled ?? false;
|
|
12946
|
+
if (!costEstimationEnabled) {
|
|
12947
|
+
return false;
|
|
12948
|
+
}
|
|
12925
12949
|
if (!constraint) return false;
|
|
12926
12950
|
if (constraint.maxPerRequest && estimatedCost > constraint.maxPerRequest) {
|
|
12927
12951
|
return true;
|
|
@@ -13195,10 +13219,13 @@ var PROVIDER_METADATA = {
|
|
|
13195
13219
|
// OpenAI runs on Azure infrastructure
|
|
13196
13220
|
regions: ["us-east", "us-west", "eu-west", "ap-southeast"],
|
|
13197
13221
|
costPerToken: {
|
|
13222
|
+
// NOTE: Despite the field name, these values are actually cost per 1000 tokens (not per single token)
|
|
13223
|
+
// Display code multiplies by 1000 to show per-1K-tokens cost
|
|
13224
|
+
// $2.50 per 1M tokens = 0.0025 per 1K tokens
|
|
13198
13225
|
input: 25e-4,
|
|
13199
|
-
// $2.50 per 1M input tokens (gpt-4o)
|
|
13226
|
+
// $2.50 per 1M input tokens (gpt-4o) = $0.0025 per 1K tokens
|
|
13200
13227
|
output: 0.01
|
|
13201
|
-
// $10.00 per 1M output tokens
|
|
13228
|
+
// $10.00 per 1M output tokens = $0.0100 per 1K tokens
|
|
13202
13229
|
},
|
|
13203
13230
|
latencyEstimate: {
|
|
13204
13231
|
p50: 800,
|
|
@@ -13404,24 +13431,35 @@ var PROVIDER_METADATA = {
|
|
|
13404
13431
|
function getProviderMetadata(providerName) {
|
|
13405
13432
|
const baseMetadata = PROVIDER_METADATA[providerName];
|
|
13406
13433
|
if (!baseMetadata) return null;
|
|
13434
|
+
let costPerToken = baseMetadata.costPerToken;
|
|
13435
|
+
const costEstimationEnabled = PRECOMPILED_CONFIG.costEstimation?.enabled ?? false;
|
|
13436
|
+
if (!costEstimationEnabled) {
|
|
13437
|
+
costPerToken = { input: 0, output: 0 };
|
|
13438
|
+
}
|
|
13407
13439
|
if (providerName === "gemini-cli") {
|
|
13408
13440
|
const streamingEnabled = flagManager.isEnabled("gemini_streaming", {
|
|
13409
13441
|
provider: providerName
|
|
13410
13442
|
});
|
|
13411
13443
|
return {
|
|
13412
13444
|
...baseMetadata,
|
|
13445
|
+
costPerToken,
|
|
13413
13446
|
features: {
|
|
13414
13447
|
...baseMetadata.features,
|
|
13415
13448
|
streaming: streamingEnabled
|
|
13416
13449
|
}
|
|
13417
13450
|
};
|
|
13418
13451
|
}
|
|
13419
|
-
return
|
|
13452
|
+
return {
|
|
13453
|
+
...baseMetadata,
|
|
13454
|
+
costPerToken
|
|
13455
|
+
};
|
|
13420
13456
|
}
|
|
13421
13457
|
function getCheapestProvider() {
|
|
13422
13458
|
let cheapest = null;
|
|
13423
13459
|
let lowestCost = Infinity;
|
|
13424
|
-
for (const
|
|
13460
|
+
for (const name of Object.keys(PROVIDER_METADATA)) {
|
|
13461
|
+
const metadata = getProviderMetadata(name);
|
|
13462
|
+
if (!metadata) continue;
|
|
13425
13463
|
const avgCost = (metadata.costPerToken.input + metadata.costPerToken.output) / 2;
|
|
13426
13464
|
if (avgCost < lowestCost) {
|
|
13427
13465
|
lowestCost = avgCost;
|
|
@@ -13929,6 +13967,9 @@ var RouterTraceLogger = class {
|
|
|
13929
13967
|
mkdirSync(logDir, { recursive: true });
|
|
13930
13968
|
}
|
|
13931
13969
|
}
|
|
13970
|
+
process.on("exit", () => this.close());
|
|
13971
|
+
process.on("SIGINT", () => this.close());
|
|
13972
|
+
process.on("SIGTERM", () => this.close());
|
|
13932
13973
|
}
|
|
13933
13974
|
/**
|
|
13934
13975
|
* Log a trace event
|
|
@@ -13939,6 +13980,10 @@ var RouterTraceLogger = class {
|
|
|
13939
13980
|
if (!this.stream && !this.streamInitializing) {
|
|
13940
13981
|
this.streamInitializing = true;
|
|
13941
13982
|
this.stream = createWriteStream(this.traceFile, { flags: "a" });
|
|
13983
|
+
this.stream.on("error", (err) => {
|
|
13984
|
+
logger.error("Trace stream error", { error: err });
|
|
13985
|
+
this.stream = void 0;
|
|
13986
|
+
});
|
|
13942
13987
|
this.streamInitializing = false;
|
|
13943
13988
|
}
|
|
13944
13989
|
if (!this.stream) {
|
|
@@ -21113,19 +21158,73 @@ Retry attempt ${attempt}/${maxAttempts}...`));
|
|
|
21113
21158
|
// v5.0.7: Pass abort signal for cancellation
|
|
21114
21159
|
};
|
|
21115
21160
|
let response;
|
|
21116
|
-
|
|
21117
|
-
|
|
21118
|
-
|
|
21119
|
-
|
|
21120
|
-
|
|
21121
|
-
|
|
21122
|
-
|
|
21123
|
-
|
|
21161
|
+
let duration = 0;
|
|
21162
|
+
try {
|
|
21163
|
+
if (options.streaming?.enabled && context.provider.executeStreaming) {
|
|
21164
|
+
response = await context.provider.executeStreaming(request, {
|
|
21165
|
+
enabled: true,
|
|
21166
|
+
onToken: options.streaming.onToken,
|
|
21167
|
+
onProgress: options.streaming.onProgress
|
|
21168
|
+
});
|
|
21169
|
+
} else {
|
|
21170
|
+
response = await context.provider.execute(request);
|
|
21171
|
+
}
|
|
21172
|
+
duration = Date.now() - startTime;
|
|
21173
|
+
} catch (primaryError) {
|
|
21174
|
+
duration = Date.now() - startTime;
|
|
21175
|
+
const fallbackProviderName = context.agent.fallbackProvider;
|
|
21176
|
+
if (fallbackProviderName && this.contextManager) {
|
|
21177
|
+
logger.warn("Primary provider failed, attempting fallback", {
|
|
21178
|
+
primary: context.provider.name,
|
|
21179
|
+
fallback: fallbackProviderName,
|
|
21180
|
+
error: primaryError.message
|
|
21181
|
+
});
|
|
21182
|
+
if (spinner) {
|
|
21183
|
+
spinner.text = `Primary provider failed, trying ${fallbackProviderName}...`;
|
|
21184
|
+
}
|
|
21185
|
+
try {
|
|
21186
|
+
const fallbackProvider = await this.contextManager.selectProvider(fallbackProviderName);
|
|
21187
|
+
context.provider = fallbackProvider;
|
|
21188
|
+
if (spinner) {
|
|
21189
|
+
spinner.text = `Executing with ${fallbackProvider.name} (fallback)...`;
|
|
21190
|
+
}
|
|
21191
|
+
const fallbackStartTime = Date.now();
|
|
21192
|
+
if (options.streaming?.enabled && fallbackProvider.executeStreaming) {
|
|
21193
|
+
response = await fallbackProvider.executeStreaming(request, {
|
|
21194
|
+
enabled: true,
|
|
21195
|
+
onToken: options.streaming.onToken,
|
|
21196
|
+
onProgress: options.streaming.onProgress
|
|
21197
|
+
});
|
|
21198
|
+
} else {
|
|
21199
|
+
response = await fallbackProvider.execute(request);
|
|
21200
|
+
}
|
|
21201
|
+
duration = Date.now() - fallbackStartTime;
|
|
21202
|
+
logger.info("Fallback provider succeeded", {
|
|
21203
|
+
fallback: fallbackProvider.name,
|
|
21204
|
+
duration
|
|
21205
|
+
});
|
|
21206
|
+
if (verbose) {
|
|
21207
|
+
console.log(chalk5.yellow(`
|
|
21208
|
+
\u26A0\uFE0F Primary provider failed, used fallback: ${fallbackProvider.name}`));
|
|
21209
|
+
}
|
|
21210
|
+
} catch (fallbackError) {
|
|
21211
|
+
logger.error("Both primary and fallback providers failed", {
|
|
21212
|
+
primary: context.provider.name,
|
|
21213
|
+
fallback: fallbackProviderName,
|
|
21214
|
+
primaryError: primaryError.message,
|
|
21215
|
+
fallbackError: fallbackError.message
|
|
21216
|
+
});
|
|
21217
|
+
const enhancedError = primaryError;
|
|
21218
|
+
enhancedError.fallbackError = fallbackError;
|
|
21219
|
+
throw enhancedError;
|
|
21220
|
+
}
|
|
21221
|
+
} else {
|
|
21222
|
+
throw primaryError;
|
|
21223
|
+
}
|
|
21124
21224
|
}
|
|
21125
21225
|
if (!response) {
|
|
21126
21226
|
throw new Error("Provider returned undefined response");
|
|
21127
21227
|
}
|
|
21128
|
-
const duration = Date.now() - startTime;
|
|
21129
21228
|
if (context.orchestration) {
|
|
21130
21229
|
const delegations = await this.delegationParser.parse(response.content, context.agent.name);
|
|
21131
21230
|
if (delegations.length > 0) {
|
|
@@ -23138,10 +23237,15 @@ var McpServer = class {
|
|
|
23138
23237
|
if (!this.initialized) {
|
|
23139
23238
|
if (!this.initializationPromise) {
|
|
23140
23239
|
this.initializationPromise = (async () => {
|
|
23141
|
-
|
|
23142
|
-
|
|
23143
|
-
|
|
23144
|
-
|
|
23240
|
+
try {
|
|
23241
|
+
await this.initializeServices();
|
|
23242
|
+
this.registerTools();
|
|
23243
|
+
this.initialized = true;
|
|
23244
|
+
logger.info("[MCP Server] Initialization complete");
|
|
23245
|
+
} catch (error) {
|
|
23246
|
+
this.initializationPromise = null;
|
|
23247
|
+
throw error;
|
|
23248
|
+
}
|
|
23145
23249
|
})();
|
|
23146
23250
|
}
|
|
23147
23251
|
await this.initializationPromise;
|
|
@@ -28509,11 +28613,12 @@ async function askTemplate() {
|
|
|
28509
28613
|
});
|
|
28510
28614
|
console.log();
|
|
28511
28615
|
const answer = await ask(`Select template (1-${templates.length})`, "1");
|
|
28512
|
-
const index = parseInt(answer) - 1;
|
|
28513
|
-
if (index
|
|
28514
|
-
|
|
28616
|
+
const index = parseInt(answer, 10) - 1;
|
|
28617
|
+
if (isNaN(index) || index < 0 || index >= templates.length) {
|
|
28618
|
+
console.log(chalk5.yellow("\n\u26A0 Invalid selection, using first template"));
|
|
28619
|
+
return templates[0].name;
|
|
28515
28620
|
}
|
|
28516
|
-
return templates[0].name;
|
|
28621
|
+
return templates[index]?.name ?? templates[0].name;
|
|
28517
28622
|
}
|
|
28518
28623
|
async function askTeam(defaultValue) {
|
|
28519
28624
|
const teams = await listAvailableTeams();
|
|
@@ -28528,11 +28633,12 @@ async function askTeam(defaultValue) {
|
|
|
28528
28633
|
console.log();
|
|
28529
28634
|
const defaultIndex = teams.findIndex((t) => t.name === defaultValue) + 1;
|
|
28530
28635
|
const answer = await ask(`Select team (1-${teams.length})`, defaultIndex > 0 ? defaultIndex.toString() : "1");
|
|
28531
|
-
const index = parseInt(answer) - 1;
|
|
28532
|
-
if (index
|
|
28533
|
-
|
|
28636
|
+
const index = parseInt(answer, 10) - 1;
|
|
28637
|
+
if (isNaN(index) || index < 0 || index >= teams.length) {
|
|
28638
|
+
console.log(chalk5.yellow("\n\u26A0 Invalid selection, using default team"));
|
|
28639
|
+
return defaultValue || teams[0]?.name || "core";
|
|
28534
28640
|
}
|
|
28535
|
-
return
|
|
28641
|
+
return teams[index]?.name ?? defaultValue ?? "core";
|
|
28536
28642
|
}
|
|
28537
28643
|
function extractDefault(value) {
|
|
28538
28644
|
if (!value || !value.includes("default:")) return void 0;
|
|
@@ -44195,6 +44301,11 @@ var PlanGenerator = class {
|
|
|
44195
44301
|
* Estimate costs
|
|
44196
44302
|
*/
|
|
44197
44303
|
estimateCosts(spec) {
|
|
44304
|
+
const costEstimationEnabled = PRECOMPILED_CONFIG.costEstimation?.enabled ?? false;
|
|
44305
|
+
if (!costEstimationEnabled) {
|
|
44306
|
+
logger.debug("Cost estimation disabled, returning $0");
|
|
44307
|
+
return { min: 0, max: 0 };
|
|
44308
|
+
}
|
|
44198
44309
|
let providerName = spec.providers?.primary?.name || "gemini-cli";
|
|
44199
44310
|
if (typeof providerName !== "string" || providerName.trim().length === 0) {
|
|
44200
44311
|
logger.warn("Invalid provider name for cost estimation, using default", {
|
|
@@ -44213,7 +44324,7 @@ var PlanGenerator = class {
|
|
|
44213
44324
|
}
|
|
44214
44325
|
const inputTokensPerActor = 2e3;
|
|
44215
44326
|
const outputTokensPerActor = 1e3;
|
|
44216
|
-
const costPerActor = inputTokensPerActor * provider.costPerToken.input + outputTokensPerActor * provider.costPerToken.output;
|
|
44327
|
+
const costPerActor = inputTokensPerActor / 1e3 * provider.costPerToken.input + outputTokensPerActor / 1e3 * provider.costPerToken.output;
|
|
44217
44328
|
const totalCost = costPerActor * spec.actors.length;
|
|
44218
44329
|
return {
|
|
44219
44330
|
min: totalCost * 0.8,
|
|
@@ -44273,9 +44384,12 @@ var PlanGenerator = class {
|
|
|
44273
44384
|
if (spec.actors.length > 1) {
|
|
44274
44385
|
recommendations.push("Enable parallel execution to reduce total duration");
|
|
44275
44386
|
}
|
|
44276
|
-
const
|
|
44277
|
-
if (
|
|
44278
|
-
|
|
44387
|
+
const costEstimationEnabled = PRECOMPILED_CONFIG.costEstimation?.enabled ?? false;
|
|
44388
|
+
if (costEstimationEnabled) {
|
|
44389
|
+
const providerName = spec.providers?.primary?.name;
|
|
44390
|
+
if (providerName === "claude-code" || providerName === "openai") {
|
|
44391
|
+
recommendations.push("Consider using gemini-cli for cost savings (5-10x cheaper)");
|
|
44392
|
+
}
|
|
44279
44393
|
}
|
|
44280
44394
|
if (!spec.observability) {
|
|
44281
44395
|
recommendations.push("Add observability configuration for production deployments");
|
|
@@ -44295,8 +44409,14 @@ var PlanGenerator = class {
|
|
|
44295
44409
|
sections.push(`- **Actors**: ${plan.overview.actorCount}`);
|
|
44296
44410
|
sections.push(`- **Phases**: ${plan.overview.phaseCount}`);
|
|
44297
44411
|
sections.push(`- **Estimated Duration**: ${plan.overview.estimatedDuration}`);
|
|
44298
|
-
|
|
44412
|
+
const isCostEstimationDisabled = plan.overview.estimatedCost.min === 0 && plan.overview.estimatedCost.max === 0;
|
|
44413
|
+
if (isCostEstimationDisabled) {
|
|
44414
|
+
sections.push(`- **Estimated Cost**: N/A (cost estimation disabled)
|
|
44415
|
+
`);
|
|
44416
|
+
} else {
|
|
44417
|
+
sections.push(`- **Estimated Cost**: $${plan.overview.estimatedCost.min.toFixed(2)} - $${plan.overview.estimatedCost.max.toFixed(2)} ${plan.overview.estimatedCost.currency}
|
|
44299
44418
|
`);
|
|
44419
|
+
}
|
|
44300
44420
|
sections.push("## Execution Phases\n");
|
|
44301
44421
|
for (const phase of plan.phases) {
|
|
44302
44422
|
sections.push(`### Phase ${phase.phase}: ${phase.name}
|
|
@@ -44358,6 +44478,7 @@ var PlanGenerator = class {
|
|
|
44358
44478
|
const match2 = duration.match(/^([\d.]+)([smh])$/);
|
|
44359
44479
|
if (!match2 || !match2[1] || !match2[2]) return 0;
|
|
44360
44480
|
const value = parseFloat(match2[1]);
|
|
44481
|
+
if (isNaN(value) || value < 0) return 0;
|
|
44361
44482
|
const unit = match2[2];
|
|
44362
44483
|
switch (unit) {
|
|
44363
44484
|
case "s":
|
|
@@ -44377,6 +44498,7 @@ var PlanGenerator = class {
|
|
|
44377
44498
|
const match2 = limit.match(/^(\d+)(KB|MB|GB)$/i);
|
|
44378
44499
|
if (!match2 || !match2[1] || !match2[2]) return 0;
|
|
44379
44500
|
const value = parseInt(match2[1], 10);
|
|
44501
|
+
if (isNaN(value) || value < 0) return 0;
|
|
44380
44502
|
const unit = match2[2].toUpperCase();
|
|
44381
44503
|
switch (unit) {
|
|
44382
44504
|
case "KB":
|
|
@@ -45958,8 +46080,14 @@ function displayPlanSummary(plan) {
|
|
|
45958
46080
|
console.log(chalk5.gray(` Actors: ${plan.overview.actorCount}`));
|
|
45959
46081
|
console.log(chalk5.gray(` Phases: ${plan.overview.phaseCount}`));
|
|
45960
46082
|
console.log(chalk5.gray(` Estimated Duration: ${plan.overview.estimatedDuration}`));
|
|
45961
|
-
|
|
46083
|
+
const isCostDisabled = plan.overview.estimatedCost.min === 0 && plan.overview.estimatedCost.max === 0;
|
|
46084
|
+
if (isCostDisabled) {
|
|
46085
|
+
console.log(chalk5.gray(` Estimated Cost: N/A (cost estimation disabled)
|
|
45962
46086
|
`));
|
|
46087
|
+
} else {
|
|
46088
|
+
console.log(chalk5.gray(` Estimated Cost: $${plan.overview.estimatedCost.min.toFixed(2)} - $${plan.overview.estimatedCost.max.toFixed(2)} ${plan.overview.estimatedCost.currency}
|
|
46089
|
+
`));
|
|
46090
|
+
}
|
|
45963
46091
|
console.log(chalk5.blue("Phases:"));
|
|
45964
46092
|
for (const phase of plan.phases) {
|
|
45965
46093
|
console.log(chalk5.cyan(` Phase ${phase.phase}: ${phase.name}`));
|
|
@@ -46161,7 +46289,12 @@ async function handleList(config, argv) {
|
|
|
46161
46289
|
if (provider.metadata && argv.verbose) {
|
|
46162
46290
|
const meta = provider.metadata;
|
|
46163
46291
|
console.log(chalk5.gray(` Cloud: ${meta.cloud} \xB7 Regions: ${meta.regions.join(", ")}`));
|
|
46164
|
-
|
|
46292
|
+
const isCostDisabled = meta.costPerToken.input === 0 && meta.costPerToken.output === 0;
|
|
46293
|
+
if (isCostDisabled) {
|
|
46294
|
+
console.log(chalk5.gray(` Cost: N/A (cost estimation disabled)`));
|
|
46295
|
+
} else {
|
|
46296
|
+
console.log(chalk5.gray(` Cost: $${(meta.costPerToken.input * 1e3).toFixed(3)}-${(meta.costPerToken.output * 1e3).toFixed(3)}/1K tokens`));
|
|
46297
|
+
}
|
|
46165
46298
|
console.log(chalk5.gray(` Latency: P50=${meta.latencyEstimate.p50}ms, P95=${meta.latencyEstimate.p95}ms`));
|
|
46166
46299
|
console.log(chalk5.gray(` Reliability: ${(meta.reliability.availability * 100).toFixed(1)}% uptime, ${(meta.reliability.errorRate * 100).toFixed(2)}% error rate`));
|
|
46167
46300
|
console.log(chalk5.gray(` Features: ${Object.entries(meta.features).filter(([_, v]) => v).map(([k]) => k).join(", ") || "none"}`));
|
|
@@ -46256,11 +46389,18 @@ async function handleInfo(argv) {
|
|
|
46256
46389
|
console.log(chalk5.gray(` Available Regions: ${metadata.regions.join(", ")}
|
|
46257
46390
|
`));
|
|
46258
46391
|
console.log(chalk5.blue("Pricing:"));
|
|
46259
|
-
|
|
46260
|
-
|
|
46261
|
-
|
|
46262
|
-
|
|
46392
|
+
const isCostDisabled = metadata.costPerToken.input === 0 && metadata.costPerToken.output === 0;
|
|
46393
|
+
if (isCostDisabled) {
|
|
46394
|
+
console.log(chalk5.gray(` Cost estimation is disabled`));
|
|
46395
|
+
console.log(chalk5.gray(` To enable, set costEstimation.enabled = true in automatosx.config.json
|
|
46396
|
+
`));
|
|
46397
|
+
} else {
|
|
46398
|
+
console.log(chalk5.gray(` Input Tokens: $${(metadata.costPerToken.input * 1e3).toFixed(3)} per 1K tokens ($${metadata.costPerToken.input.toFixed(6)} per token)`));
|
|
46399
|
+
console.log(chalk5.gray(` Output Tokens: $${(metadata.costPerToken.output * 1e3).toFixed(3)} per 1K tokens ($${metadata.costPerToken.output.toFixed(6)} per token)`));
|
|
46400
|
+
const avgCost = (metadata.costPerToken.input + metadata.costPerToken.output) / 2;
|
|
46401
|
+
console.log(chalk5.gray(` Average: $${(avgCost * 1e6).toFixed(2)} per 1M tokens
|
|
46263
46402
|
`));
|
|
46403
|
+
}
|
|
46264
46404
|
console.log(chalk5.blue("Performance:"));
|
|
46265
46405
|
console.log(chalk5.gray(` P50 Latency: ${metadata.latencyEstimate.p50}ms`));
|
|
46266
46406
|
console.log(chalk5.gray(` P95 Latency: ${metadata.latencyEstimate.p95}ms`));
|
|
@@ -46411,17 +46551,33 @@ function displayTraceEvent(line) {
|
|
|
46411
46551
|
const phase = phaseColor(event.phase.toUpperCase().padEnd(12));
|
|
46412
46552
|
const provider = event.provider ? chalk5.bold(event.provider.padEnd(15)) : "".padEnd(15);
|
|
46413
46553
|
let summary = "";
|
|
46414
|
-
if (event.
|
|
46415
|
-
summary =
|
|
46554
|
+
if (!event.data || typeof event.data !== "object") {
|
|
46555
|
+
summary = chalk5.gray("(no data)");
|
|
46556
|
+
} else if (event.phase === "selection") {
|
|
46557
|
+
const candidates = event.data.candidates?.length ?? 0;
|
|
46558
|
+
const reason = event.data.reason ?? "unknown";
|
|
46559
|
+
summary = `${candidates} candidates \u2192 ${chalk5.bold(reason)}`;
|
|
46416
46560
|
} else if (event.phase === "policy") {
|
|
46417
|
-
|
|
46561
|
+
const goal = event.data.goal ?? "unknown";
|
|
46562
|
+
const after = event.data.providersAfterFilter ?? 0;
|
|
46563
|
+
const before = event.data.providersBeforeFilter ?? 0;
|
|
46564
|
+
summary = `goal=${goal}, passed=${after}/${before}`;
|
|
46418
46565
|
} else if (event.phase === "execution") {
|
|
46419
46566
|
const status = event.data.success ? chalk5.green("\u2713") : chalk5.red("\u2717");
|
|
46420
|
-
|
|
46567
|
+
const duration = event.data.durationMs ?? 0;
|
|
46568
|
+
const cost = event.data.cost ?? 0;
|
|
46569
|
+
if (cost === 0) {
|
|
46570
|
+
summary = `${status} ${duration}ms`;
|
|
46571
|
+
} else {
|
|
46572
|
+
summary = `${status} ${duration}ms, $${cost.toFixed(6)}`;
|
|
46573
|
+
}
|
|
46421
46574
|
} else if (event.phase === "degradation") {
|
|
46422
|
-
|
|
46575
|
+
const reason = event.data.reason ?? "unknown";
|
|
46576
|
+
const toProvider = event.data.toProvider ?? "failed";
|
|
46577
|
+
summary = `${reason} \u2192 ${toProvider}`;
|
|
46423
46578
|
} else if (event.phase === "error") {
|
|
46424
|
-
|
|
46579
|
+
const errorMsg = event.data.error ?? "unknown error";
|
|
46580
|
+
summary = chalk5.red(errorMsg);
|
|
46425
46581
|
}
|
|
46426
46582
|
console.log(`${chalk5.gray(timestamp)} ${phase} ${provider} ${summary}`);
|
|
46427
46583
|
} catch (error) {
|