@agentconnect/host 0.2.0 → 0.2.2
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/host.js +144 -49
- package/dist/providers/codex.js +42 -2
- package/dist/types.d.ts +2 -1
- package/package.json +1 -1
package/dist/host.js
CHANGED
|
@@ -132,14 +132,21 @@ function createHostRuntime(options) {
|
|
|
132
132
|
return;
|
|
133
133
|
recordCapability(`model.${providerId}`);
|
|
134
134
|
}
|
|
135
|
+
function recordProviderCapability(providerId) {
|
|
136
|
+
recordCapability(`model.${providerId}`);
|
|
137
|
+
}
|
|
135
138
|
async function getCachedStatus(provider, options = {}) {
|
|
139
|
+
if (options.force) {
|
|
140
|
+
statusCache.delete(provider.id);
|
|
141
|
+
statusInFlight.delete(provider.id);
|
|
142
|
+
}
|
|
136
143
|
const cached = statusCache.get(provider.id);
|
|
137
144
|
const now = Date.now();
|
|
138
|
-
if (cached && now - cached.at < statusCacheTtlMs) {
|
|
145
|
+
if (!options.force && cached && now - cached.at < statusCacheTtlMs) {
|
|
139
146
|
return cached.status;
|
|
140
147
|
}
|
|
141
148
|
const existing = statusInFlight.get(provider.id);
|
|
142
|
-
if (existing)
|
|
149
|
+
if (!options.force && existing)
|
|
143
150
|
return existing;
|
|
144
151
|
if (options.allowFast && provider.fastStatus) {
|
|
145
152
|
try {
|
|
@@ -184,12 +191,50 @@ function createHostRuntime(options) {
|
|
|
184
191
|
statusInFlight.set(provider.id, promise);
|
|
185
192
|
return promise;
|
|
186
193
|
}
|
|
194
|
+
async function isModelForProvider(model, providerId) {
|
|
195
|
+
try {
|
|
196
|
+
const models = await listModels();
|
|
197
|
+
if (!models.length)
|
|
198
|
+
return true;
|
|
199
|
+
const match = models.find((entry) => entry.id === model);
|
|
200
|
+
if (match)
|
|
201
|
+
return match.provider === providerId;
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
return resolveProviderForModel(model) === providerId;
|
|
207
|
+
}
|
|
208
|
+
async function pickDefaultModel(providerId) {
|
|
209
|
+
try {
|
|
210
|
+
const recent = await listRecentModels(providerId);
|
|
211
|
+
if (recent.length > 0)
|
|
212
|
+
return recent[0].id;
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
// ignore recent model lookup failures
|
|
216
|
+
}
|
|
217
|
+
try {
|
|
218
|
+
const models = await listModels();
|
|
219
|
+
const match = models.find((entry) => entry.provider === providerId);
|
|
220
|
+
if (match)
|
|
221
|
+
return match.id;
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
// ignore model lookup failures
|
|
225
|
+
}
|
|
226
|
+
if (providerId === 'claude')
|
|
227
|
+
return 'default';
|
|
228
|
+
if (providerId === 'local')
|
|
229
|
+
return 'local';
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
187
232
|
function invalidateStatus(providerId) {
|
|
188
233
|
if (!providerId)
|
|
189
234
|
return;
|
|
190
235
|
statusCache.delete(providerId);
|
|
191
236
|
}
|
|
192
|
-
function emitSessionEvent(
|
|
237
|
+
function emitSessionEvent(emit, sessionId, type, data) {
|
|
193
238
|
if (process.env.AGENTCONNECT_DEBUG?.trim()) {
|
|
194
239
|
try {
|
|
195
240
|
console.log(`[AgentConnect][Session ${sessionId}] ${type} ${JSON.stringify(data)}`);
|
|
@@ -198,7 +243,7 @@ function createHostRuntime(options) {
|
|
|
198
243
|
console.log(`[AgentConnect][Session ${sessionId}] ${type}`);
|
|
199
244
|
}
|
|
200
245
|
}
|
|
201
|
-
|
|
246
|
+
emit({
|
|
202
247
|
jsonrpc: '2.0',
|
|
203
248
|
method: 'acp.session.event',
|
|
204
249
|
params: { sessionId, type, data },
|
|
@@ -252,7 +297,10 @@ function createHostRuntime(options) {
|
|
|
252
297
|
responder.error(id, 'AC_ERR_UNSUPPORTED', 'Unknown provider');
|
|
253
298
|
return;
|
|
254
299
|
}
|
|
255
|
-
const
|
|
300
|
+
const statusOptions = params.options ?? {};
|
|
301
|
+
const allowFast = statusOptions.fast !== false;
|
|
302
|
+
const force = Boolean(statusOptions.force);
|
|
303
|
+
const status = await getCachedStatus(provider, { allowFast, force });
|
|
256
304
|
responder.reply(id, {
|
|
257
305
|
provider: {
|
|
258
306
|
id: provider.id,
|
|
@@ -395,13 +443,39 @@ function createHostRuntime(options) {
|
|
|
395
443
|
}
|
|
396
444
|
if (method === 'acp.sessions.create') {
|
|
397
445
|
const sessionId = `sess_${Math.random().toString(36).slice(2, 10)}`;
|
|
398
|
-
const
|
|
446
|
+
const rawProvider = params.provider;
|
|
447
|
+
if (rawProvider && !providers[rawProvider]) {
|
|
448
|
+
responder.error(id, 'AC_ERR_UNSUPPORTED', 'Unknown provider');
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
const rawModel = typeof params.model === 'string' ? params.model.trim() : '';
|
|
452
|
+
const modelInput = rawModel ? rawModel : undefined;
|
|
453
|
+
if (!rawProvider && !modelInput) {
|
|
454
|
+
responder.error(id, 'AC_ERR_INVALID_ARGS', 'Model or provider is required');
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
const providerId = rawProvider ?? resolveProviderForModel(modelInput);
|
|
458
|
+
let model = modelInput ?? null;
|
|
459
|
+
if (rawProvider && modelInput) {
|
|
460
|
+
const matches = await isModelForProvider(modelInput, rawProvider);
|
|
461
|
+
if (!matches) {
|
|
462
|
+
responder.error(id, 'AC_ERR_INVALID_ARGS', 'Model does not belong to provider');
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
if (rawProvider && !modelInput) {
|
|
467
|
+
model = await pickDefaultModel(rawProvider);
|
|
468
|
+
}
|
|
399
469
|
const reasoningEffort = params.reasoningEffort || null;
|
|
400
470
|
const cwd = params.cwd ? resolveAppPathInternal(params.cwd) : undefined;
|
|
401
471
|
const repoRoot = params.repoRoot ? resolveAppPathInternal(params.repoRoot) : undefined;
|
|
402
472
|
const providerDetailLevel = params.providerDetailLevel || undefined;
|
|
403
|
-
|
|
404
|
-
|
|
473
|
+
if (model) {
|
|
474
|
+
recordModelCapability(model);
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
recordProviderCapability(providerId);
|
|
478
|
+
}
|
|
405
479
|
sessions.set(sessionId, {
|
|
406
480
|
id: sessionId,
|
|
407
481
|
providerId,
|
|
@@ -421,43 +495,39 @@ function createHostRuntime(options) {
|
|
|
421
495
|
const sessionId = params.sessionId;
|
|
422
496
|
const existing = sessions.get(sessionId);
|
|
423
497
|
if (!existing) {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
const cwd = params.cwd ? resolveAppPathInternal(params.cwd) : undefined;
|
|
427
|
-
const repoRoot = params.repoRoot ? resolveAppPathInternal(params.repoRoot) : undefined;
|
|
428
|
-
const providerDetailLevel = params.providerDetailLevel || undefined;
|
|
429
|
-
recordModelCapability(model);
|
|
430
|
-
sessions.set(sessionId, {
|
|
431
|
-
id: sessionId,
|
|
432
|
-
providerId: resolveProviderForModel(model),
|
|
433
|
-
model,
|
|
434
|
-
providerSessionId: params.providerSessionId || null,
|
|
435
|
-
reasoningEffort,
|
|
436
|
-
cwd,
|
|
437
|
-
repoRoot,
|
|
438
|
-
providerDetailLevel: providerDetailLevel === 'raw' || providerDetailLevel === 'minimal'
|
|
439
|
-
? providerDetailLevel
|
|
440
|
-
: undefined,
|
|
441
|
-
});
|
|
498
|
+
responder.error(id, 'AC_ERR_INVALID_ARGS', 'Unknown session');
|
|
499
|
+
return;
|
|
442
500
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
501
|
+
if (params.providerSessionId) {
|
|
502
|
+
existing.providerSessionId = String(params.providerSessionId);
|
|
503
|
+
}
|
|
504
|
+
if (params.cwd) {
|
|
505
|
+
existing.cwd = resolveAppPathInternal(params.cwd);
|
|
506
|
+
}
|
|
507
|
+
if (params.repoRoot) {
|
|
508
|
+
existing.repoRoot = resolveAppPathInternal(params.repoRoot);
|
|
509
|
+
}
|
|
510
|
+
if (params.providerDetailLevel) {
|
|
511
|
+
const level = String(params.providerDetailLevel);
|
|
512
|
+
if (level === 'raw' || level === 'minimal') {
|
|
513
|
+
existing.providerDetailLevel = level;
|
|
452
514
|
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
515
|
+
}
|
|
516
|
+
if (!existing.model && typeof params.model === 'string' && params.model.trim()) {
|
|
517
|
+
const candidate = params.model.trim();
|
|
518
|
+
const matches = await isModelForProvider(candidate, existing.providerId);
|
|
519
|
+
if (!matches) {
|
|
520
|
+
responder.error(id, 'AC_ERR_INVALID_ARGS', 'Model does not belong to provider');
|
|
521
|
+
return;
|
|
458
522
|
}
|
|
523
|
+
existing.model = candidate;
|
|
524
|
+
}
|
|
525
|
+
if (existing.model) {
|
|
459
526
|
recordModelCapability(existing.model);
|
|
460
527
|
}
|
|
528
|
+
else {
|
|
529
|
+
recordProviderCapability(existing.providerId);
|
|
530
|
+
}
|
|
461
531
|
responder.reply(id, { sessionId });
|
|
462
532
|
return;
|
|
463
533
|
}
|
|
@@ -469,7 +539,18 @@ function createHostRuntime(options) {
|
|
|
469
539
|
responder.error(id, 'AC_ERR_INVALID_ARGS', 'Unknown session');
|
|
470
540
|
return;
|
|
471
541
|
}
|
|
472
|
-
|
|
542
|
+
let model = session.model;
|
|
543
|
+
if (!model) {
|
|
544
|
+
model = await pickDefaultModel(session.providerId);
|
|
545
|
+
if (model)
|
|
546
|
+
session.model = model;
|
|
547
|
+
}
|
|
548
|
+
if (model) {
|
|
549
|
+
recordModelCapability(model);
|
|
550
|
+
}
|
|
551
|
+
else {
|
|
552
|
+
recordProviderCapability(session.providerId);
|
|
553
|
+
}
|
|
473
554
|
const provider = providers[session.providerId];
|
|
474
555
|
if (!provider) {
|
|
475
556
|
responder.error(id, 'AC_ERR_UNSUPPORTED', 'Unknown provider');
|
|
@@ -495,52 +576,66 @@ function createHostRuntime(options) {
|
|
|
495
576
|
const providerDetailLevel = params.providerDetailLevel === 'raw' || params.providerDetailLevel === 'minimal'
|
|
496
577
|
? params.providerDetailLevel
|
|
497
578
|
: session.providerDetailLevel || 'minimal';
|
|
498
|
-
|
|
579
|
+
const runToken = `run_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
580
|
+
activeRuns.set(sessionId, { controller, emit: responder.emit, token: runToken });
|
|
499
581
|
let sawError = false;
|
|
500
582
|
provider
|
|
501
583
|
.runPrompt({
|
|
502
584
|
prompt: message,
|
|
503
585
|
resumeSessionId: session.providerSessionId,
|
|
504
|
-
model:
|
|
586
|
+
model: model ?? undefined,
|
|
505
587
|
reasoningEffort: session.reasoningEffort,
|
|
506
588
|
repoRoot,
|
|
507
589
|
cwd,
|
|
508
590
|
providerDetailLevel,
|
|
509
591
|
signal: controller.signal,
|
|
510
592
|
onEvent: (event) => {
|
|
593
|
+
const current = activeRuns.get(sessionId);
|
|
594
|
+
if (!current || current.token !== runToken)
|
|
595
|
+
return;
|
|
511
596
|
if (event.type === 'error') {
|
|
512
597
|
sawError = true;
|
|
513
598
|
}
|
|
514
599
|
if (sawError && event.type === 'final') {
|
|
515
600
|
return;
|
|
516
601
|
}
|
|
517
|
-
emitSessionEvent(
|
|
602
|
+
emitSessionEvent(current.emit, sessionId, event.type, { ...event });
|
|
518
603
|
},
|
|
519
604
|
})
|
|
520
605
|
.then((result) => {
|
|
606
|
+
const current = activeRuns.get(sessionId);
|
|
607
|
+
if (!current || current.token !== runToken)
|
|
608
|
+
return;
|
|
521
609
|
if (result?.sessionId) {
|
|
522
610
|
session.providerSessionId = result.sessionId;
|
|
523
611
|
}
|
|
524
612
|
})
|
|
525
613
|
.catch((err) => {
|
|
614
|
+
const current = activeRuns.get(sessionId);
|
|
615
|
+
if (!current || current.token !== runToken)
|
|
616
|
+
return;
|
|
526
617
|
if (!sawError) {
|
|
527
|
-
emitSessionEvent(
|
|
618
|
+
emitSessionEvent(current.emit, sessionId, 'error', {
|
|
528
619
|
message: err?.message || 'Provider error',
|
|
529
620
|
});
|
|
530
621
|
}
|
|
531
622
|
})
|
|
532
623
|
.finally(() => {
|
|
533
|
-
activeRuns.
|
|
624
|
+
const current = activeRuns.get(sessionId);
|
|
625
|
+
if (current && current.token === runToken) {
|
|
626
|
+
activeRuns.delete(sessionId);
|
|
627
|
+
}
|
|
534
628
|
});
|
|
535
629
|
responder.reply(id, { accepted: true });
|
|
536
630
|
return;
|
|
537
631
|
}
|
|
538
632
|
if (method === 'acp.sessions.cancel') {
|
|
539
633
|
const sessionId = params.sessionId;
|
|
540
|
-
const
|
|
541
|
-
if (
|
|
542
|
-
controller.abort();
|
|
634
|
+
const run = activeRuns.get(sessionId);
|
|
635
|
+
if (run) {
|
|
543
636
|
activeRuns.delete(sessionId);
|
|
637
|
+
run.controller.abort();
|
|
638
|
+
emitSessionEvent(run.emit, sessionId, 'final', { cancelled: true });
|
|
544
639
|
}
|
|
545
640
|
responder.reply(id, { cancelled: true });
|
|
546
641
|
return;
|
package/dist/providers/codex.js
CHANGED
|
@@ -227,7 +227,7 @@ async function hasCodexAuth() {
|
|
|
227
227
|
return false;
|
|
228
228
|
}
|
|
229
229
|
function buildCodexExecArgs(options) {
|
|
230
|
-
const { prompt, cdTarget, resumeSessionId, model, reasoningEffort, mode } = options;
|
|
230
|
+
const { prompt, cdTarget, resumeSessionId, model, reasoningEffort, providerDetailLevel, mode } = options;
|
|
231
231
|
const args = ['exec', '--skip-git-repo-check'];
|
|
232
232
|
if (mode === 'legacy') {
|
|
233
233
|
args.push('--json', '-C', cdTarget);
|
|
@@ -236,6 +236,27 @@ function buildCodexExecArgs(options) {
|
|
|
236
236
|
args.push('--experimental-json', '--cd', cdTarget);
|
|
237
237
|
}
|
|
238
238
|
args.push('--yolo');
|
|
239
|
+
const summarySetting = process.env.AGENTCONNECT_CODEX_REASONING_SUMMARY;
|
|
240
|
+
const summary = summarySetting && summarySetting.trim()
|
|
241
|
+
? summarySetting.trim()
|
|
242
|
+
: 'detailed';
|
|
243
|
+
const summaryDisabled = ['0', 'false', 'off', 'none'].includes(summary.toLowerCase());
|
|
244
|
+
if (!summaryDisabled) {
|
|
245
|
+
args.push('--config', `model_reasoning_summary=${summary}`);
|
|
246
|
+
const supportsSetting = process.env.AGENTCONNECT_CODEX_SUPPORTS_REASONING_SUMMARIES;
|
|
247
|
+
const supportsValue = supportsSetting && supportsSetting.trim() ? supportsSetting.trim() : 'true';
|
|
248
|
+
args.push('--config', `model_supports_reasoning_summaries=${supportsValue}`);
|
|
249
|
+
}
|
|
250
|
+
const verbositySetting = process.env.AGENTCONNECT_CODEX_MODEL_VERBOSITY;
|
|
251
|
+
if (verbositySetting && verbositySetting.trim()) {
|
|
252
|
+
args.push('--config', `model_verbosity=${verbositySetting.trim()}`);
|
|
253
|
+
}
|
|
254
|
+
const rawSetting = process.env.AGENTCONNECT_CODEX_SHOW_RAW_REASONING;
|
|
255
|
+
const rawEnabled = providerDetailLevel === 'raw' ||
|
|
256
|
+
(rawSetting ? ['1', 'true', 'yes', 'on'].includes(rawSetting.trim().toLowerCase()) : false);
|
|
257
|
+
if (rawEnabled) {
|
|
258
|
+
args.push('--config', 'show_raw_agent_reasoning=true');
|
|
259
|
+
}
|
|
239
260
|
if (model) {
|
|
240
261
|
args.push('--model', String(model));
|
|
241
262
|
}
|
|
@@ -637,6 +658,7 @@ export function runCodexPrompt({ prompt, resumeSessionId, model, reasoningEffort
|
|
|
637
658
|
resumeSessionId,
|
|
638
659
|
model,
|
|
639
660
|
reasoningEffort,
|
|
661
|
+
providerDetailLevel,
|
|
640
662
|
mode,
|
|
641
663
|
});
|
|
642
664
|
const argsPreview = [...args];
|
|
@@ -646,7 +668,25 @@ export function runCodexPrompt({ prompt, resumeSessionId, model, reasoningEffort
|
|
|
646
668
|
debugLog('Codex', 'spawn', { command, args: argsPreview, cwd: runDir, mode });
|
|
647
669
|
const child = spawn(command, args, {
|
|
648
670
|
cwd: runDir,
|
|
649
|
-
env:
|
|
671
|
+
env: (() => {
|
|
672
|
+
const env = { ...process.env };
|
|
673
|
+
if (!env.RUST_LOG) {
|
|
674
|
+
const override = process.env.AGENTCONNECT_CODEX_RUST_LOG;
|
|
675
|
+
if (override && override.trim()) {
|
|
676
|
+
env.RUST_LOG = override.trim();
|
|
677
|
+
}
|
|
678
|
+
else {
|
|
679
|
+
const debugFlag = process.env.AGENTCONNECT_CODEX_DEBUG_LOGS;
|
|
680
|
+
const enabled = debugFlag
|
|
681
|
+
? ['1', 'true', 'yes', 'on'].includes(debugFlag.trim().toLowerCase())
|
|
682
|
+
: false;
|
|
683
|
+
if (enabled) {
|
|
684
|
+
env.RUST_LOG = 'codex_exec=debug,codex_core=debug';
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
return env;
|
|
689
|
+
})(),
|
|
650
690
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
651
691
|
});
|
|
652
692
|
if (signal) {
|
package/dist/types.d.ts
CHANGED
|
@@ -144,6 +144,7 @@ export interface SessionEvent {
|
|
|
144
144
|
input?: unknown;
|
|
145
145
|
output?: unknown;
|
|
146
146
|
timestampMs?: number;
|
|
147
|
+
cancelled?: boolean;
|
|
147
148
|
}
|
|
148
149
|
export interface RunPromptOptions {
|
|
149
150
|
prompt: string;
|
|
@@ -182,7 +183,7 @@ export interface Provider {
|
|
|
182
183
|
export interface SessionState {
|
|
183
184
|
id: string;
|
|
184
185
|
providerId: ProviderId;
|
|
185
|
-
model: string;
|
|
186
|
+
model: string | null;
|
|
186
187
|
providerSessionId: string | null;
|
|
187
188
|
reasoningEffort: string | null;
|
|
188
189
|
cwd?: string;
|