@wundam/orchex 1.0.0-rc.6 → 1.0.0-rc.8
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 +3 -3
- package/dist/cloud-sync.d.ts +8 -0
- package/dist/cloud-sync.js +26 -0
- package/dist/config.d.ts +4 -0
- package/dist/config.js +15 -0
- package/dist/index.js +78 -29
- package/dist/intelligence/cost-tracker.d.ts +1 -1
- package/dist/intelligence/event-types.d.ts +89 -0
- package/dist/intelligence/event-types.js +1 -0
- package/dist/intelligence/execution-report.d.ts +3 -0
- package/dist/intelligence/execution-report.js +3 -0
- package/dist/intelligence/learning-engine.d.ts +1 -1
- package/dist/intelligence/pattern-analyzer.d.ts +1 -1
- package/dist/intelligence/slicing-metrics.d.ts +1 -1
- package/dist/orchestrator.js +9 -2
- package/dist/tools.js +36 -0
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Your AI assistant does tasks one at a time. Orchex makes it do 10 at once — sa
|
|
|
19
19
|
## Prerequisites
|
|
20
20
|
|
|
21
21
|
- [Node.js](https://nodejs.org/) >= 18
|
|
22
|
-
- LLM API key
|
|
22
|
+
- LLM API key — set via environment variable **or** store on the [dashboard](https://orchex.dev/dashboard/keys) and sync with `orchex login`:
|
|
23
23
|
- `ANTHROPIC_API_KEY` for Anthropic Claude
|
|
24
24
|
- `OPENAI_API_KEY` for OpenAI (GPT-4.1, o1, o3)
|
|
25
25
|
- `GEMINI_API_KEY` for Google Gemini
|
|
@@ -47,11 +47,11 @@ Connect to orchex cloud for managed execution:
|
|
|
47
47
|
orchex login
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
Your browser opens — log in or create a free account, click **Allow**. Token saved automatically.
|
|
50
|
+
Your browser opens — log in or create a free account, click **Allow**. Token saved automatically. API keys stored on the dashboard are synced to your local machine so `orchex run` works without environment variables.
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
53
|
orchex status # Check tier and trial runs
|
|
54
|
-
orchex logout # Clear credentials
|
|
54
|
+
orchex logout # Clear credentials and cached keys
|
|
55
55
|
orchex --help # All commands
|
|
56
56
|
```
|
|
57
57
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Config } from './config.js';
|
|
2
|
+
import type { ExecutionReport } from './intelligence/execution-report.js';
|
|
3
|
+
/**
|
|
4
|
+
* Fire-and-forget sync of an execution report to the cloud dashboard.
|
|
5
|
+
* Only runs when user is logged in (mode=cloud + apiKey present).
|
|
6
|
+
* Never blocks or throws — network failures are silently ignored.
|
|
7
|
+
*/
|
|
8
|
+
export declare function syncReportToCloud(config: Config, report: ExecutionReport): Promise<void>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fire-and-forget sync of an execution report to the cloud dashboard.
|
|
3
|
+
* Only runs when user is logged in (mode=cloud + apiKey present).
|
|
4
|
+
* Never blocks or throws — network failures are silently ignored.
|
|
5
|
+
*/
|
|
6
|
+
export async function syncReportToCloud(config, report) {
|
|
7
|
+
if (config.mode !== 'cloud' || !config.apiKey)
|
|
8
|
+
return;
|
|
9
|
+
const apiUrl = config.apiUrl;
|
|
10
|
+
try {
|
|
11
|
+
const resp = await fetch(`${apiUrl}/api/v1/history/sync`, {
|
|
12
|
+
method: 'POST',
|
|
13
|
+
headers: {
|
|
14
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
15
|
+
'Content-Type': 'application/json',
|
|
16
|
+
},
|
|
17
|
+
body: JSON.stringify({ report }),
|
|
18
|
+
});
|
|
19
|
+
if (resp.status === 401) {
|
|
20
|
+
console.warn('Cloud sync: token expired. Run `orchex login` to re-authenticate.');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Network error — silently skip
|
|
25
|
+
}
|
|
26
|
+
}
|
package/dist/config.d.ts
CHANGED
|
@@ -7,6 +7,10 @@ export type LLMProvider = z.infer<typeof LLMProviderSchema>;
|
|
|
7
7
|
* Priority: ORCHEX_PROVIDER env var > first available API key
|
|
8
8
|
*/
|
|
9
9
|
export declare function detectProvider(): LLMProvider;
|
|
10
|
+
/**
|
|
11
|
+
* Log the detected provider and masked key at startup.
|
|
12
|
+
*/
|
|
13
|
+
export declare function logProviderDetection(): void;
|
|
10
14
|
/**
|
|
11
15
|
* Get the API key for a specific provider from environment variables.
|
|
12
16
|
*/
|
package/dist/config.js
CHANGED
|
@@ -3,6 +3,8 @@ import * as path from 'path';
|
|
|
3
3
|
import * as os from 'os';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { TierIdSchema } from './tiers.js';
|
|
6
|
+
import { createLogger } from './logging.js';
|
|
7
|
+
const log = createLogger('config');
|
|
6
8
|
// Well-known URLs
|
|
7
9
|
export const PRODUCTION_URL = 'https://orchex.dev';
|
|
8
10
|
// ============================================================================
|
|
@@ -35,6 +37,19 @@ export function detectProvider() {
|
|
|
35
37
|
// Default to Anthropic (original behavior)
|
|
36
38
|
return 'anthropic';
|
|
37
39
|
}
|
|
40
|
+
function maskKey(key) {
|
|
41
|
+
if (key.length <= 8)
|
|
42
|
+
return '****';
|
|
43
|
+
return key.slice(0, 4) + '...' + key.slice(-4);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Log the detected provider and masked key at startup.
|
|
47
|
+
*/
|
|
48
|
+
export function logProviderDetection() {
|
|
49
|
+
const provider = detectProvider();
|
|
50
|
+
const key = getProviderApiKey(provider);
|
|
51
|
+
log.info({ provider, key: key ? maskKey(key) : 'none' }, 'provider_detected');
|
|
52
|
+
}
|
|
38
53
|
/**
|
|
39
54
|
* Get the API key for a specific provider from environment variables.
|
|
40
55
|
*/
|
package/dist/index.js
CHANGED
|
@@ -190,6 +190,7 @@ ORCHESTRATION:
|
|
|
190
190
|
orchex run "..." --yes Skip approval prompt (auto-approve)
|
|
191
191
|
orchex run "..." --dry-run Generate plan only, don't execute
|
|
192
192
|
orchex run "..." --provider openai --model gpt-4.1
|
|
193
|
+
orchex complete --archive Archive active orchestration and unblock future runs
|
|
193
194
|
|
|
194
195
|
CLOUD COMMANDS:
|
|
195
196
|
orchex login Authenticate with orchex cloud (opens browser)
|
|
@@ -208,7 +209,7 @@ CONFIG:
|
|
|
208
209
|
orchex config --staging Configure for staging server (reads ORCHEX_API_URL)
|
|
209
210
|
|
|
210
211
|
ENVIRONMENT VARIABLES:
|
|
211
|
-
ORCHEX_API_URL Override API server URL (e.g. https://
|
|
212
|
+
ORCHEX_API_URL Override API server URL (e.g. https://orchex.dev)
|
|
212
213
|
Priority: --api-url flag > ORCHEX_API_URL > config file > default
|
|
213
214
|
|
|
214
215
|
MCP SERVER (invoked by your AI assistant):
|
|
@@ -506,40 +507,64 @@ async function handleRunCommand(args) {
|
|
|
506
507
|
}
|
|
507
508
|
// Check for existing orchestration
|
|
508
509
|
if (await manifestExists(projectDir)) {
|
|
509
|
-
console.error('An active orchestration already exists. Run `orchex complete --archive`
|
|
510
|
+
console.error('An active orchestration already exists. Run `orchex complete --archive` to clear it.');
|
|
510
511
|
process.exit(1);
|
|
511
512
|
}
|
|
512
513
|
// Init and execute
|
|
513
514
|
console.log(`\nInitializing orchestration: "${plan.title}"\n`);
|
|
514
515
|
await initOrchestration(projectDir, plan.title, streamDefs);
|
|
515
516
|
const allResponses = [];
|
|
516
|
-
let
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
517
|
+
let executionError;
|
|
518
|
+
try {
|
|
519
|
+
let done = false;
|
|
520
|
+
let waveNum = 1;
|
|
521
|
+
while (!done) {
|
|
522
|
+
console.log(`Executing wave ${waveNum}...`);
|
|
523
|
+
const response = await executeWave(projectDir, exec, { model: modelFlag });
|
|
524
|
+
allResponses.push(response);
|
|
525
|
+
const completed = response.streams.filter(s => s.status === 'complete').length;
|
|
526
|
+
const failed = response.streams.filter(s => s.status === 'failed').length;
|
|
527
|
+
console.log(` Wave ${waveNum}: ${completed} complete, ${failed} failed`);
|
|
528
|
+
done = response.done;
|
|
529
|
+
waveNum++;
|
|
530
|
+
}
|
|
531
|
+
// Generate report
|
|
532
|
+
const manifest = await loadManifest(projectDir);
|
|
533
|
+
const report = generateReport(manifest, allResponses);
|
|
534
|
+
const reportPath = await saveReportLocally(projectDir, report);
|
|
535
|
+
// Sync report to cloud dashboard (fire-and-forget, only if logged in)
|
|
536
|
+
const { syncReportToCloud } = await import('./cloud-sync.js');
|
|
537
|
+
await syncReportToCloud(config, report);
|
|
538
|
+
// Learning summary
|
|
539
|
+
const summary = generateLearningSummary(report);
|
|
540
|
+
console.log('\n--- Orchex learned ---');
|
|
541
|
+
for (const insight of summary) {
|
|
542
|
+
console.log(` ${insight}`);
|
|
543
|
+
}
|
|
544
|
+
console.log(`\nReport saved: ${reportPath}`);
|
|
545
|
+
console.log(`Quality score: ${report.planQualityScore}/100\n`);
|
|
546
|
+
// Mark first-run complete after successful orchestration
|
|
547
|
+
if (await isFirstRun(projectDir)) {
|
|
548
|
+
await markFirstRunComplete(projectDir);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
catch (err) {
|
|
552
|
+
executionError = err;
|
|
553
|
+
console.error(`\nExecution error: ${executionError.message}`);
|
|
554
|
+
}
|
|
555
|
+
finally {
|
|
556
|
+
// Always archive to unblock future runs
|
|
557
|
+
try {
|
|
558
|
+
const { archiveOrchestration } = await import('./manifest.js');
|
|
559
|
+
const archiveName = await archiveOrchestration(projectDir);
|
|
560
|
+
console.log(`Orchestration archived: ${archiveName}`);
|
|
561
|
+
}
|
|
562
|
+
catch {
|
|
563
|
+
// Best-effort — report is already saved if execution succeeded
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
if (executionError) {
|
|
567
|
+
process.exit(1);
|
|
543
568
|
}
|
|
544
569
|
}
|
|
545
570
|
async function main() {
|
|
@@ -584,6 +609,30 @@ async function main() {
|
|
|
584
609
|
}
|
|
585
610
|
return;
|
|
586
611
|
}
|
|
612
|
+
if (args[0] === 'complete') {
|
|
613
|
+
const { manifestExists, archiveOrchestration } = await import('./manifest.js');
|
|
614
|
+
const subArgs = args.slice(1);
|
|
615
|
+
const pdFlag = subArgs.indexOf('--project-dir');
|
|
616
|
+
const projectDir = pdFlag !== -1 && subArgs[pdFlag + 1] ? subArgs[pdFlag + 1] : process.cwd();
|
|
617
|
+
if (!(await manifestExists(projectDir))) {
|
|
618
|
+
console.log('No active orchestration to archive.');
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
if (subArgs.includes('--archive')) {
|
|
622
|
+
try {
|
|
623
|
+
const archiveName = await archiveOrchestration(projectDir);
|
|
624
|
+
console.log(`Orchestration archived: ${archiveName}`);
|
|
625
|
+
}
|
|
626
|
+
catch (err) {
|
|
627
|
+
console.error(`Archive failed: ${err.message}`);
|
|
628
|
+
process.exit(1);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
console.error('Usage: orchex complete --archive');
|
|
633
|
+
}
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
587
636
|
if (args[0] === '--version' || args[0] === '-v') {
|
|
588
637
|
const { createRequire } = await import('module');
|
|
589
638
|
const require = createRequire(import.meta.url);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Token cost tracking and estimation for Orchex Learn.
|
|
3
3
|
* Provides cost estimation and aggregation for multi-provider token usage.
|
|
4
4
|
*/
|
|
5
|
-
import type { TelemetryEvent } from '
|
|
5
|
+
import type { TelemetryEvent } from './event-types.js';
|
|
6
6
|
/**
|
|
7
7
|
* Token costs per 1000 tokens (in USD).
|
|
8
8
|
* Prices as of February 2026 - should be updated periodically.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { ErrorCategory } from './error-analyzer.js';
|
|
2
|
+
import type { BudgetViolationType } from '../types.js';
|
|
3
|
+
export interface TelemetryEvent {
|
|
4
|
+
id: string;
|
|
5
|
+
sessionHash: string;
|
|
6
|
+
eventType: 'orchestration_start' | 'orchestration_complete' | 'stream_complete' | 'stream_failed' | 'self_heal_triggered';
|
|
7
|
+
timestamp: string;
|
|
8
|
+
durationMs?: number;
|
|
9
|
+
streamCount?: number;
|
|
10
|
+
waveCount?: number;
|
|
11
|
+
parallelCount?: number;
|
|
12
|
+
success?: boolean;
|
|
13
|
+
errorCategory?: ErrorCategory;
|
|
14
|
+
retryCount?: number;
|
|
15
|
+
selfHealCount?: number;
|
|
16
|
+
complexityScore?: number;
|
|
17
|
+
tokensInput?: number;
|
|
18
|
+
tokensOutput?: number;
|
|
19
|
+
provider?: string;
|
|
20
|
+
model?: string;
|
|
21
|
+
tier?: string;
|
|
22
|
+
/** Estimated context tokens before execution */
|
|
23
|
+
contextTokensEstimated?: number;
|
|
24
|
+
/** Actual context tokens from API response */
|
|
25
|
+
contextTokensActual?: number;
|
|
26
|
+
/** Budget utilization ratio (0-1) */
|
|
27
|
+
contextBudgetUtilization?: number;
|
|
28
|
+
/** Whether budget limits were exceeded */
|
|
29
|
+
budgetViolationType?: BudgetViolationType;
|
|
30
|
+
/** Provider's context window limit for this model */
|
|
31
|
+
providerContextLimit?: number;
|
|
32
|
+
/** Whether cache was hit */
|
|
33
|
+
cacheHit?: boolean;
|
|
34
|
+
/** Tokens read from cache */
|
|
35
|
+
cacheReadTokens?: number;
|
|
36
|
+
/** Tokens written to cache */
|
|
37
|
+
cacheWriteTokens?: number;
|
|
38
|
+
/** Milliseconds saved by parallel execution */
|
|
39
|
+
timeSavedMs?: number;
|
|
40
|
+
/** Hypothetical sequential execution time in ms */
|
|
41
|
+
sequentialMs?: number;
|
|
42
|
+
/** Actual parallel execution time in ms */
|
|
43
|
+
parallelMs?: number;
|
|
44
|
+
/** Stream name for category-based analysis */
|
|
45
|
+
streamName?: string;
|
|
46
|
+
/** SHA-256 hash of the prompt sent to LLM */
|
|
47
|
+
promptHash?: string;
|
|
48
|
+
/** SHA-256 hash of the artifact response */
|
|
49
|
+
artifactHash?: string;
|
|
50
|
+
}
|
|
51
|
+
export interface TelemetryAggregate {
|
|
52
|
+
period: string;
|
|
53
|
+
orchestrationsTotal: number;
|
|
54
|
+
orchestrationsSuccess: number;
|
|
55
|
+
orchestrationsFailed: number;
|
|
56
|
+
streamsTotal: number;
|
|
57
|
+
streamsSuccess: number;
|
|
58
|
+
streamsFailed: number;
|
|
59
|
+
avgDurationMs?: number;
|
|
60
|
+
p50DurationMs?: number;
|
|
61
|
+
p95DurationMs?: number;
|
|
62
|
+
errorsByCategory: Record<ErrorCategory, number>;
|
|
63
|
+
selfHealTriggered: number;
|
|
64
|
+
selfHealSuccess: number;
|
|
65
|
+
tokensInputTotal: number;
|
|
66
|
+
tokensOutputTotal: number;
|
|
67
|
+
/** Average context budget utilization (0-1) */
|
|
68
|
+
avgContextUtilization?: number;
|
|
69
|
+
/** Count of soft limit violations */
|
|
70
|
+
softViolationCount: number;
|
|
71
|
+
/** Count of hard limit violations */
|
|
72
|
+
hardViolationCount: number;
|
|
73
|
+
/** Streams that failed due to context exceeded */
|
|
74
|
+
contextExceededFailures: number;
|
|
75
|
+
/** Cache hit rate (0-1) */
|
|
76
|
+
cacheHitRate?: number;
|
|
77
|
+
/** Total tokens read from cache */
|
|
78
|
+
cacheReadTokensTotal: number;
|
|
79
|
+
/** Total tokens written to cache */
|
|
80
|
+
cacheWriteTokensTotal: number;
|
|
81
|
+
/** Estimated cost savings from cache */
|
|
82
|
+
estimatedCacheSavings?: number;
|
|
83
|
+
/** Total milliseconds saved by parallel execution */
|
|
84
|
+
timeSavedMsTotal: number;
|
|
85
|
+
/** Total hypothetical sequential time in ms */
|
|
86
|
+
sequentialMsTotal: number;
|
|
87
|
+
/** Total actual parallel time in ms */
|
|
88
|
+
parallelMsTotal: number;
|
|
89
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -13,6 +13,9 @@ export interface ReportStreamResult {
|
|
|
13
13
|
executionTimeMs?: number;
|
|
14
14
|
selfHealCount: number;
|
|
15
15
|
errorCategory?: string;
|
|
16
|
+
provider?: string;
|
|
17
|
+
model?: string;
|
|
18
|
+
filesChanged?: string[];
|
|
16
19
|
}
|
|
17
20
|
/**
|
|
18
21
|
* Full execution report — deterministic, no LLM needed.
|
|
@@ -51,6 +51,9 @@ export function generateReport(manifest, responses, options) {
|
|
|
51
51
|
executionTimeMs: sr.executionTimeMs,
|
|
52
52
|
selfHealCount: fixStreamIds.has(sr.id) ? 1 : 0,
|
|
53
53
|
errorCategory: sr.errorDetail?.category,
|
|
54
|
+
provider: sr.provider,
|
|
55
|
+
model: sr.model,
|
|
56
|
+
filesChanged: sr.filesChanged,
|
|
54
57
|
}));
|
|
55
58
|
// Token aggregation
|
|
56
59
|
let totalInput = 0;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Learning engine for adaptive threshold adjustment in Orchex Learn.
|
|
3
3
|
* Correlates context characteristics with execution success and adapts thresholds.
|
|
4
4
|
*/
|
|
5
|
-
import type { TelemetryEvent } from '
|
|
5
|
+
import type { TelemetryEvent } from './event-types.js';
|
|
6
6
|
/**
|
|
7
7
|
* Stream categories for per-category learning.
|
|
8
8
|
* Canonical source of truth for stream categorization across all intelligence modules.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* NOTE: StreamCategory and categorizeStream are imported from learning-engine.ts
|
|
6
6
|
* to maintain a single source of truth for stream categorization.
|
|
7
7
|
*/
|
|
8
|
-
import type { TelemetryEvent } from '
|
|
8
|
+
import type { TelemetryEvent } from './event-types.js';
|
|
9
9
|
import type { StreamResult } from '../types.js';
|
|
10
10
|
import { type StreamCategory, categorizeStream as categorizeStreamFromLearningEngine } from './learning-engine.js';
|
|
11
11
|
export type { StreamCategory };
|
package/dist/orchestrator.js
CHANGED
|
@@ -12,7 +12,7 @@ import { runCommands } from './commands.js';
|
|
|
12
12
|
import * as fs from 'fs/promises';
|
|
13
13
|
import * as path from 'path';
|
|
14
14
|
import { loadConfig, getConfiguredModel } from './config.js';
|
|
15
|
-
import { getTier } from './tiers.js';
|
|
15
|
+
import { getTier, getEffectiveTier } from './tiers.js';
|
|
16
16
|
import { broadcaster } from './execution-broadcaster.js';
|
|
17
17
|
import { streamResultToTelemetryEvent, appendLocalEvents, runLearningCycle, } from './intelligence/learning-engine.js';
|
|
18
18
|
import { routeStream, loadRoutingRules } from './intelligence/smart-router.js';
|
|
@@ -649,7 +649,14 @@ async function executeWaveInternal(projectDir, executor, options, logger) {
|
|
|
649
649
|
// 7a. SELF-HEAL — generate fix streams for failed streams (tier-gated)
|
|
650
650
|
const fixStreamsGenerated = [];
|
|
651
651
|
const currentManifest = await loadManifest(projectDir);
|
|
652
|
-
const
|
|
652
|
+
const effectiveTierId = config.mode === 'cloud' && config.apiKey
|
|
653
|
+
? getEffectiveTier({
|
|
654
|
+
tier: config.tier ?? 'free',
|
|
655
|
+
createdAt: config.accountCreatedAt ?? new Date().toISOString(),
|
|
656
|
+
trialRunsRemaining: config.trialRunsRemaining ?? 0,
|
|
657
|
+
})
|
|
658
|
+
: (config.tier ?? 'free');
|
|
659
|
+
const tier = getTier(effectiveTierId);
|
|
653
660
|
if (tier.selfHealing === 'full') {
|
|
654
661
|
for (const sr of streamResults) {
|
|
655
662
|
if (sr.status !== 'failed' || sr.id === 'unknown')
|
package/dist/tools.js
CHANGED
|
@@ -865,6 +865,18 @@ export function registerTools(server, executor, context) {
|
|
|
865
865
|
done: true,
|
|
866
866
|
}]);
|
|
867
867
|
await saveReportLocally(projectDir, report);
|
|
868
|
+
// Sync to cloud if locally authenticated (no ToolContext historyStore)
|
|
869
|
+
if (!context?.historyStore) {
|
|
870
|
+
try {
|
|
871
|
+
const { loadConfig } = await import('./config.js');
|
|
872
|
+
const { syncReportToCloud } = await import('./cloud-sync.js');
|
|
873
|
+
const syncConfig = await loadConfig();
|
|
874
|
+
await syncReportToCloud(syncConfig, report);
|
|
875
|
+
}
|
|
876
|
+
catch {
|
|
877
|
+
// Sync is best-effort
|
|
878
|
+
}
|
|
879
|
+
}
|
|
868
880
|
const summary = generateLearningSummary(report);
|
|
869
881
|
await logger.info('execution_report_saved', {
|
|
870
882
|
runId: report.runId,
|
|
@@ -980,6 +992,18 @@ export function registerTools(server, executor, context) {
|
|
|
980
992
|
const reportManifest = await loadManifest(projectDir);
|
|
981
993
|
const report = generateReport(reportManifest, [result]);
|
|
982
994
|
await saveReportLocally(projectDir, report);
|
|
995
|
+
// Sync to cloud if locally authenticated (no ToolContext historyStore)
|
|
996
|
+
if (!context?.historyStore) {
|
|
997
|
+
try {
|
|
998
|
+
const { loadConfig } = await import('./config.js');
|
|
999
|
+
const { syncReportToCloud } = await import('./cloud-sync.js');
|
|
1000
|
+
const syncConfig = await loadConfig();
|
|
1001
|
+
await syncReportToCloud(syncConfig, report);
|
|
1002
|
+
}
|
|
1003
|
+
catch {
|
|
1004
|
+
// Sync is best-effort
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
983
1007
|
const summary = generateLearningSummary(report);
|
|
984
1008
|
await logger.info('execution_report_saved', {
|
|
985
1009
|
runId: report.runId,
|
|
@@ -1637,6 +1661,18 @@ export function registerTools(server, executor, context) {
|
|
|
1637
1661
|
const manifest = await loadManifest(projectDir);
|
|
1638
1662
|
const report = generateReport(manifest, allResponses);
|
|
1639
1663
|
await saveReportLocally(projectDir, report);
|
|
1664
|
+
// Sync to cloud if locally authenticated (no ToolContext historyStore)
|
|
1665
|
+
if (!context?.historyStore) {
|
|
1666
|
+
try {
|
|
1667
|
+
const { loadConfig } = await import('./config.js');
|
|
1668
|
+
const { syncReportToCloud } = await import('./cloud-sync.js');
|
|
1669
|
+
const syncConfig = await loadConfig();
|
|
1670
|
+
await syncReportToCloud(syncConfig, report);
|
|
1671
|
+
}
|
|
1672
|
+
catch {
|
|
1673
|
+
// Sync is best-effort
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1640
1676
|
// 8. Generate learning summary
|
|
1641
1677
|
const summary = generateLearningSummary(report);
|
|
1642
1678
|
// 9. Mark first-run complete
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wundam/orchex",
|
|
3
|
-
"
|
|
3
|
+
"mcpName": "com.orchex/orchex",
|
|
4
|
+
"version": "1.0.0-rc.8",
|
|
4
5
|
"description": "Autopilot AI orchestration — auto-plan, parallelize, and execute with ownership enforcement",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"main": "dist/index.js",
|
|
@@ -75,6 +76,8 @@
|
|
|
75
76
|
"dist/config.d.ts",
|
|
76
77
|
"dist/key-cache.js",
|
|
77
78
|
"dist/key-cache.d.ts",
|
|
79
|
+
"dist/cloud-sync.js",
|
|
80
|
+
"dist/cloud-sync.d.ts",
|
|
78
81
|
"dist/context-builder.js",
|
|
79
82
|
"dist/context-builder.d.ts",
|
|
80
83
|
"dist/cost.js",
|