@myagentroam/node 0.9.119 → 0.9.120
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.
|
@@ -24,13 +24,11 @@ export class CodexRunner extends AbstractRunner {
|
|
|
24
24
|
fastEnabled = false;
|
|
25
25
|
environmentFingerprint;
|
|
26
26
|
environmentRuns = new Set();
|
|
27
|
-
profileCache
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
profileCache;
|
|
28
|
+
profileCacheVersion;
|
|
29
|
+
profileCacheTimer;
|
|
30
|
+
profileRefresh;
|
|
30
31
|
profileClients = new Set();
|
|
31
|
-
profileKeyByEnvironment = new Map();
|
|
32
|
-
latestProfileCache;
|
|
33
|
-
selectedProfileKey;
|
|
34
32
|
profileGeneration = 0;
|
|
35
33
|
constructor(client = new CodexAppServerClient(), profileClientFactory = () => new CodexAppServerClient()) {
|
|
36
34
|
super();
|
|
@@ -43,40 +41,39 @@ export class CodexRunner extends AbstractRunner {
|
|
|
43
41
|
claudeCodeAvailable: capabilities.claudeCode.available,
|
|
44
42
|
openCodeAvailable: capabilities.openCode?.available === true
|
|
45
43
|
}).find((profile) => profile.runner === this.name);
|
|
46
|
-
return { ...base, models: this.
|
|
44
|
+
return { ...base, models: this.profileCache?.profile.models ?? [] };
|
|
47
45
|
}
|
|
48
46
|
cachedProfile(capabilities, environment = {}) {
|
|
49
47
|
const base = this.profile(capabilities);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
return this.profileCache === undefined ||
|
|
49
|
+
this.profileCacheVersion !== capabilities.codex.version
|
|
50
|
+
? { ...base, models: [] }
|
|
51
|
+
: this.profileCache.profile;
|
|
53
52
|
}
|
|
54
53
|
async refreshProfile(capabilities, workspace, environment = {}, waitForRefresh = false) {
|
|
55
54
|
void workspace;
|
|
56
55
|
const base = this.profile(capabilities);
|
|
57
56
|
if (!capabilities.codex.available)
|
|
58
57
|
return { ...base, models: [] };
|
|
59
|
-
const
|
|
60
|
-
this.profileKeyByEnvironment.set(codexSecretEnvironmentFingerprint(environment), key);
|
|
61
|
-
this.selectedProfileKey = key;
|
|
58
|
+
const version = capabilities.codex.version;
|
|
62
59
|
const now = Date.now();
|
|
63
|
-
const cached = this.profileCache
|
|
60
|
+
const cached = this.profileCacheVersion === version ? this.profileCache : undefined;
|
|
64
61
|
if (cached?.successful === true && now < cached.fetchedAt + CODEX_MODEL_CACHE_MS)
|
|
65
|
-
return
|
|
62
|
+
return cached.profile;
|
|
66
63
|
if (cached?.successful === true) {
|
|
67
64
|
if (now >= cached.retryAt) {
|
|
68
|
-
const refresh = this.refreshCodexProfile(
|
|
65
|
+
const refresh = this.refreshCodexProfile(version, base, environment);
|
|
69
66
|
if (waitForRefresh)
|
|
70
67
|
return refresh;
|
|
71
68
|
}
|
|
72
|
-
return
|
|
69
|
+
return cached.profile;
|
|
73
70
|
}
|
|
74
71
|
if (cached !== undefined && now < cached.retryAt)
|
|
75
72
|
return cached.profile;
|
|
76
|
-
return this.refreshCodexProfile(
|
|
73
|
+
return this.refreshCodexProfile(version, base, environment);
|
|
77
74
|
}
|
|
78
|
-
refreshCodexProfile(
|
|
79
|
-
const existing = this.
|
|
75
|
+
refreshCodexProfile(version, base, environment) {
|
|
76
|
+
const existing = this.profileRefresh;
|
|
80
77
|
if (existing !== undefined)
|
|
81
78
|
return existing;
|
|
82
79
|
const generation = this.profileGeneration;
|
|
@@ -88,11 +85,8 @@ export class CodexRunner extends AbstractRunner {
|
|
|
88
85
|
successful: true,
|
|
89
86
|
retryAt: 0
|
|
90
87
|
};
|
|
91
|
-
if (generation === this.profileGeneration)
|
|
92
|
-
this.cacheProfile(
|
|
93
|
-
if (this.selectedProfileKey === key)
|
|
94
|
-
this.latestProfileCache = cache;
|
|
95
|
-
}
|
|
88
|
+
if (generation === this.profileGeneration)
|
|
89
|
+
this.cacheProfile(version, cache);
|
|
96
90
|
return cache.profile;
|
|
97
91
|
})
|
|
98
92
|
.catch((error) => {
|
|
@@ -101,12 +95,12 @@ export class CodexRunner extends AbstractRunner {
|
|
|
101
95
|
});
|
|
102
96
|
if (generation !== this.profileGeneration)
|
|
103
97
|
return { ...base, models: [] };
|
|
104
|
-
const cached = this.profileCache
|
|
98
|
+
const cached = this.profileCacheVersion === version ? this.profileCache : undefined;
|
|
105
99
|
if (cached !== undefined) {
|
|
106
100
|
cached.retryAt = Date.now() + CODEX_MODEL_FAILURE_RETRY_MS;
|
|
107
101
|
return cached.profile;
|
|
108
102
|
}
|
|
109
|
-
this.cacheProfile(
|
|
103
|
+
this.cacheProfile(version, {
|
|
110
104
|
profile: { ...base, models: [] },
|
|
111
105
|
defaultConfiguration: emptyCodexConfiguration(),
|
|
112
106
|
fetchedAt: 0,
|
|
@@ -115,33 +109,24 @@ export class CodexRunner extends AbstractRunner {
|
|
|
115
109
|
});
|
|
116
110
|
return { ...base, models: [] };
|
|
117
111
|
})
|
|
118
|
-
.finally(() =>
|
|
119
|
-
|
|
112
|
+
.finally(() => {
|
|
113
|
+
if (this.profileRefresh === refresh)
|
|
114
|
+
this.profileRefresh = undefined;
|
|
115
|
+
});
|
|
116
|
+
this.profileRefresh = refresh;
|
|
120
117
|
return refresh;
|
|
121
118
|
}
|
|
122
|
-
|
|
123
|
-
if (
|
|
124
|
-
this.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
this.profileCache.set(key, cache);
|
|
132
|
-
const timer = setTimeout(() => {
|
|
133
|
-
this.profileCacheTimers.delete(key);
|
|
134
|
-
this.profileCache.delete(key);
|
|
135
|
-
for (const [environmentKey, profileKey] of this.profileKeyByEnvironment)
|
|
136
|
-
if (profileKey === key)
|
|
137
|
-
this.profileKeyByEnvironment.delete(environmentKey);
|
|
138
|
-
if (this.selectedProfileKey === key) {
|
|
139
|
-
this.selectedProfileKey = undefined;
|
|
140
|
-
this.latestProfileCache = undefined;
|
|
141
|
-
}
|
|
119
|
+
cacheProfile(version, cache) {
|
|
120
|
+
if (this.profileCacheTimer !== undefined)
|
|
121
|
+
clearTimeout(this.profileCacheTimer);
|
|
122
|
+
this.profileCache = cache;
|
|
123
|
+
this.profileCacheVersion = version;
|
|
124
|
+
this.profileCacheTimer = setTimeout(() => {
|
|
125
|
+
this.profileCacheTimer = undefined;
|
|
126
|
+
this.profileCache = undefined;
|
|
127
|
+
this.profileCacheVersion = undefined;
|
|
142
128
|
}, CODEX_PROFILE_ENTRY_TTL_MS);
|
|
143
|
-
|
|
144
|
-
this.profileCacheTimers.set(key, timer);
|
|
129
|
+
this.profileCacheTimer.unref();
|
|
145
130
|
}
|
|
146
131
|
async fetchCodexProfile(base, environment) {
|
|
147
132
|
const client = this.profileClientFactory();
|
|
@@ -306,11 +291,8 @@ export class CodexRunner extends AbstractRunner {
|
|
|
306
291
|
profile.models.some((model) => model.id === configuration.model && model.supportedEfforts.includes(configuration.effort)) &&
|
|
307
292
|
profile.accessOptions.some((option) => option.id === configuration.access));
|
|
308
293
|
}
|
|
309
|
-
profileCacheForEnvironment(
|
|
310
|
-
|
|
311
|
-
return this.latestProfileCache;
|
|
312
|
-
const key = this.profileKeyByEnvironment.get(codexSecretEnvironmentFingerprint(environment));
|
|
313
|
-
return key === undefined ? undefined : this.profileCache.get(key);
|
|
294
|
+
profileCacheForEnvironment(_environment) {
|
|
295
|
+
return this.profileCache;
|
|
314
296
|
}
|
|
315
297
|
async resumeExternal(external, context) {
|
|
316
298
|
if (external.runner !== this.name ||
|
|
@@ -483,13 +465,12 @@ export class CodexRunner extends AbstractRunner {
|
|
|
483
465
|
this.client.clearEnvironment();
|
|
484
466
|
this.environmentFingerprint = undefined;
|
|
485
467
|
this.environmentRuns.clear();
|
|
486
|
-
|
|
487
|
-
clearTimeout(
|
|
488
|
-
this.
|
|
489
|
-
this.profileCache
|
|
490
|
-
this.
|
|
491
|
-
this.
|
|
492
|
-
this.selectedProfileKey = undefined;
|
|
468
|
+
if (this.profileCacheTimer !== undefined)
|
|
469
|
+
clearTimeout(this.profileCacheTimer);
|
|
470
|
+
this.profileCacheTimer = undefined;
|
|
471
|
+
this.profileCache = undefined;
|
|
472
|
+
this.profileCacheVersion = undefined;
|
|
473
|
+
this.profileRefresh = undefined;
|
|
493
474
|
}
|
|
494
475
|
request(method, params) {
|
|
495
476
|
return this.client.request(method, params);
|
|
@@ -537,19 +518,6 @@ export class CodexRunner extends AbstractRunner {
|
|
|
537
518
|
function emptyCodexConfiguration() {
|
|
538
519
|
return { runner: 'codex', model: '', effort: '', access: 'on-request' };
|
|
539
520
|
}
|
|
540
|
-
function codexEnvironmentFingerprint(environment, version) {
|
|
541
|
-
return createHash('sha256')
|
|
542
|
-
.update(JSON.stringify({
|
|
543
|
-
environment: Object.entries(environment).sort(([left], [right]) => left.localeCompare(right)),
|
|
544
|
-
version: version ?? null
|
|
545
|
-
}))
|
|
546
|
-
.digest('base64url');
|
|
547
|
-
}
|
|
548
|
-
function codexSecretEnvironmentFingerprint(environment) {
|
|
549
|
-
return createHash('sha256')
|
|
550
|
-
.update(JSON.stringify(Object.entries(environment).sort(([left], [right]) => left.localeCompare(right))))
|
|
551
|
-
.digest('base64url');
|
|
552
|
-
}
|
|
553
521
|
function codexModelPage(value) {
|
|
554
522
|
if (!isPlainRecord(value) || !Array.isArray(value.data))
|
|
555
523
|
throw new Error('CODEX_MODELS_INVALID');
|
|
@@ -18,9 +18,9 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
18
18
|
discoveryScope = 'WORKSPACE_REQUIRED';
|
|
19
19
|
contextLimits = new Map();
|
|
20
20
|
contextLimitsExpiresAt = 0;
|
|
21
|
-
profileCache
|
|
22
|
-
profileRetryAt =
|
|
23
|
-
|
|
21
|
+
profileCache;
|
|
22
|
+
profileRetryAt = 0;
|
|
23
|
+
profileRefresh;
|
|
24
24
|
profileGeneration = 0;
|
|
25
25
|
execution = new Map();
|
|
26
26
|
managedTurns = new Map();
|
|
@@ -41,7 +41,7 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
41
41
|
}
|
|
42
42
|
cachedProfile(capabilities, environment = {}) {
|
|
43
43
|
this.pruneProfileCaches(Date.now());
|
|
44
|
-
const cached = this.profileCache
|
|
44
|
+
const cached = this.profileCache;
|
|
45
45
|
return cached === undefined
|
|
46
46
|
? this.profile(capabilities)
|
|
47
47
|
: { ...this.profile(capabilities), models: cached.models };
|
|
@@ -50,10 +50,9 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
50
50
|
if (capabilities.openCode?.available !== true) {
|
|
51
51
|
return this.profile(capabilities);
|
|
52
52
|
}
|
|
53
|
-
const cacheKey = this.environmentFingerprint(environment);
|
|
54
53
|
const now = Date.now();
|
|
55
54
|
this.pruneProfileCaches(now);
|
|
56
|
-
const cached = this.profileCache
|
|
55
|
+
const cached = this.profileCache;
|
|
57
56
|
if (cached !== undefined && cached.expiresAt > now) {
|
|
58
57
|
nodeLog('runner.opencode.profile.cache-hit', {
|
|
59
58
|
models: cached.models.length,
|
|
@@ -63,24 +62,24 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
63
62
|
this.contextLimitsExpiresAt = cached.expiresAt;
|
|
64
63
|
return { ...this.profile(capabilities), models: cached.models };
|
|
65
64
|
}
|
|
66
|
-
if (now <
|
|
65
|
+
if (now < this.profileRetryAt)
|
|
67
66
|
return cached === undefined
|
|
68
67
|
? this.profile(capabilities)
|
|
69
68
|
: { ...this.profile(capabilities), models: cached.models };
|
|
70
|
-
const current = this.
|
|
69
|
+
const current = this.profileRefresh;
|
|
71
70
|
if (current !== undefined) {
|
|
72
71
|
nodeLog('runner.opencode.profile.single-flight-joined', {});
|
|
73
72
|
return current;
|
|
74
73
|
}
|
|
75
74
|
const generation = this.profileGeneration;
|
|
76
|
-
const refresh = this.fetchProfile(capabilities, environment,
|
|
77
|
-
if (this.
|
|
78
|
-
this.
|
|
75
|
+
const refresh = this.fetchProfile(capabilities, environment, generation, cached).finally(() => {
|
|
76
|
+
if (this.profileRefresh === refresh)
|
|
77
|
+
this.profileRefresh = undefined;
|
|
79
78
|
});
|
|
80
|
-
this.
|
|
79
|
+
this.profileRefresh = refresh;
|
|
81
80
|
return refresh;
|
|
82
81
|
}
|
|
83
|
-
async fetchProfile(capabilities, environment,
|
|
82
|
+
async fetchProfile(capabilities, environment, generation, stale) {
|
|
84
83
|
const client = this.managedClient(environment, 'runner-profile');
|
|
85
84
|
const startedAt = performance.now();
|
|
86
85
|
try {
|
|
@@ -92,14 +91,13 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
92
91
|
return this.profile(capabilities);
|
|
93
92
|
this.contextLimits = contextLimits;
|
|
94
93
|
this.contextLimitsExpiresAt = expiresAt;
|
|
95
|
-
this.profileCache
|
|
94
|
+
this.profileCache = {
|
|
96
95
|
expiresAt,
|
|
97
96
|
discardAt: Date.now() + PROFILE_STALE_TTL_MS,
|
|
98
|
-
environmentFingerprint: cacheKey,
|
|
99
97
|
models,
|
|
100
98
|
contextLimits
|
|
101
|
-
}
|
|
102
|
-
this.profileRetryAt
|
|
99
|
+
};
|
|
100
|
+
this.profileRetryAt = 0;
|
|
103
101
|
nodeLog('runner.opencode.profile.providers.completed', {
|
|
104
102
|
models: models.length,
|
|
105
103
|
durationMs: Math.round(performance.now() - startedAt)
|
|
@@ -109,7 +107,7 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
109
107
|
catch {
|
|
110
108
|
if (generation !== this.profileGeneration)
|
|
111
109
|
return this.profile(capabilities);
|
|
112
|
-
this.profileRetryAt
|
|
110
|
+
this.profileRetryAt = Date.now() + PROFILE_FAILURE_RETRY_MS;
|
|
113
111
|
nodeLog('runner.opencode.profile.providers.failed', {
|
|
114
112
|
durationMs: Math.round(performance.now() - startedAt)
|
|
115
113
|
});
|
|
@@ -121,10 +119,6 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
121
119
|
? this.profile(capabilities)
|
|
122
120
|
: { ...this.profile(capabilities), models: stale.models };
|
|
123
121
|
}
|
|
124
|
-
environmentFingerprint(environment) {
|
|
125
|
-
const entries = Object.entries(environment).sort(([left], [right]) => left.localeCompare(right));
|
|
126
|
-
return createHash('sha256').update(JSON.stringify(entries)).digest('hex');
|
|
127
|
-
}
|
|
128
122
|
available(capabilities) {
|
|
129
123
|
return capabilities.openCode?.available === true;
|
|
130
124
|
}
|
|
@@ -160,21 +154,16 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
160
154
|
}
|
|
161
155
|
cachedModels(environment) {
|
|
162
156
|
this.pruneProfileCaches(Date.now());
|
|
163
|
-
|
|
164
|
-
return
|
|
165
|
-
.filter((entry) => entry.environmentFingerprint === fingerprint)
|
|
166
|
-
.flatMap((entry) => entry.models);
|
|
157
|
+
void environment;
|
|
158
|
+
return this.profileCache?.models ?? [];
|
|
167
159
|
}
|
|
168
160
|
pruneProfileCaches(now) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
this.profileCache
|
|
173
|
-
this.
|
|
174
|
-
|
|
175
|
-
for (const [key, retryAt] of this.profileRetryAt)
|
|
176
|
-
if (retryAt <= now && !this.profileCache.has(key) && !this.profileRefreshes.has(key))
|
|
177
|
-
this.profileRetryAt.delete(key);
|
|
161
|
+
if (this.profileCache !== undefined && this.profileCache.discardAt <= now)
|
|
162
|
+
this.profileCache = undefined;
|
|
163
|
+
if (this.profileRetryAt <= now &&
|
|
164
|
+
this.profileCache === undefined &&
|
|
165
|
+
this.profileRefresh === undefined)
|
|
166
|
+
this.profileRetryAt = 0;
|
|
178
167
|
}
|
|
179
168
|
mcpConfiguration(raw, secrets) {
|
|
180
169
|
const servers = super.mcpConfiguration(raw, secrets);
|
|
@@ -340,9 +329,9 @@ export class OpenCodeRunner extends AbstractRunner {
|
|
|
340
329
|
execution.abort.abort();
|
|
341
330
|
this.execution.clear();
|
|
342
331
|
this.managedTurns.clear();
|
|
343
|
-
this.profileCache
|
|
344
|
-
this.
|
|
345
|
-
this.profileRetryAt
|
|
332
|
+
this.profileCache = undefined;
|
|
333
|
+
this.profileRefresh = undefined;
|
|
334
|
+
this.profileRetryAt = 0;
|
|
346
335
|
this.contextLimits = new Map();
|
|
347
336
|
this.contextLimitsExpiresAt = 0;
|
|
348
337
|
const stopping = [
|
|
@@ -41,6 +41,14 @@ export class RunnerRegistry {
|
|
|
41
41
|
try {
|
|
42
42
|
return await runner.refreshProfile(capabilities, workspace, environment, waitForRefresh);
|
|
43
43
|
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
nodeLog('runner.profile.refresh.failed', {
|
|
46
|
+
runner: runner.name,
|
|
47
|
+
workspaceId: workspace?.id,
|
|
48
|
+
error: error instanceof Error ? error.message : String(error)
|
|
49
|
+
});
|
|
50
|
+
return runner.cachedProfile(capabilities, environment);
|
|
51
|
+
}
|
|
44
52
|
finally {
|
|
45
53
|
const durationMs = Math.round(performance.now() - startedAt);
|
|
46
54
|
if (durationMs >= 100)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/node",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.120",
|
|
4
4
|
"description": "MyAgentRoam Node runtime CLI.",
|
|
5
5
|
"license": "Apache-2.0 AND GPL-2.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"npm": "11.12.1",
|
|
31
31
|
"ws": "^8.21.3",
|
|
32
32
|
"zod": "4.4.3",
|
|
33
|
-
"@myagentroam/
|
|
34
|
-
"@myagentroam/
|
|
35
|
-
"@myagentroam/
|
|
33
|
+
"@myagentroam/agent": "0.9.120",
|
|
34
|
+
"@myagentroam/code-navigation": "0.9.120",
|
|
35
|
+
"@myagentroam/protocol": "0.9.120"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/ws": "^8.18.1"
|