nexus-agents 2.72.0 → 2.72.1
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/{chunk-2JMUX5UA.js → chunk-C3JGKBL2.js} +2 -2
- package/dist/{chunk-3HR6UJ2E.js → chunk-J4VR2WNI.js} +731 -2
- package/dist/chunk-J4VR2WNI.js.map +1 -0
- package/dist/{chunk-XHVDKY3X.js → chunk-YOREAPF6.js} +3 -3
- package/dist/cli.js +3 -3
- package/dist/index.d.ts +530 -51
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/{setup-command-DVEBFKR2.js → setup-command-BWUFMZ7U.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-3HR6UJ2E.js.map +0 -1
- /package/dist/{chunk-2JMUX5UA.js.map → chunk-C3JGKBL2.js.map} +0 -0
- /package/dist/{chunk-XHVDKY3X.js.map → chunk-YOREAPF6.js.map} +0 -0
- /package/dist/{setup-command-DVEBFKR2.js.map → setup-command-BWUFMZ7U.js.map} +0 -0
|
@@ -67,7 +67,7 @@ import {
|
|
|
67
67
|
clampTaskTtl,
|
|
68
68
|
getAvailabilityCache,
|
|
69
69
|
resolveFallback
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-YOREAPF6.js";
|
|
71
71
|
import {
|
|
72
72
|
DEFAULTS
|
|
73
73
|
} from "./chunk-2MD5MWCK.js";
|
|
@@ -14309,6 +14309,733 @@ async function loadAllExternalPacks(packs, logger55) {
|
|
|
14309
14309
|
return { loaded, errors };
|
|
14310
14310
|
}
|
|
14311
14311
|
|
|
14312
|
+
// src/config/model-identity.ts
|
|
14313
|
+
var VENDOR_PATTERNS = [
|
|
14314
|
+
{ vendor: "anthropic", regex: /\b(claude|anthropic)\b/ },
|
|
14315
|
+
// OpenAI: gpt, o1-o9 reasoning, chatgpt, openai prefix
|
|
14316
|
+
{ vendor: "openai", regex: /\b(gpt|o[1-9]|chatgpt|openai)\b/ },
|
|
14317
|
+
{ vendor: "google", regex: /\b(gemini|bison|gecko|palm|google)\b/ },
|
|
14318
|
+
{ vendor: "meta", regex: /\b(llama|meta-llama|meta)\b/ },
|
|
14319
|
+
{ vendor: "qwen", regex: /\b(qwen)\b/ },
|
|
14320
|
+
{ vendor: "nvidia", regex: /\b(nemotron|nvidia)\b/ },
|
|
14321
|
+
{ vendor: "mistral", regex: /\b(mistral|mixtral|codestral)\b/ },
|
|
14322
|
+
{ vendor: "cohere", regex: /\b(command-r|command|cohere)\b/ },
|
|
14323
|
+
{ vendor: "deepseek", regex: /\b(deepseek)\b/ }
|
|
14324
|
+
];
|
|
14325
|
+
var FAMILY_PATTERNS = [
|
|
14326
|
+
// Anthropic
|
|
14327
|
+
{ vendor: "anthropic", family: "claude-opus", regex: /\b(opus)\b/ },
|
|
14328
|
+
{ vendor: "anthropic", family: "claude-sonnet", regex: /\b(sonnet)\b/ },
|
|
14329
|
+
{ vendor: "anthropic", family: "claude-haiku", regex: /\b(haiku)\b/ },
|
|
14330
|
+
// OpenAI
|
|
14331
|
+
{ vendor: "openai", family: "o-reasoning", regex: /\bo[1-9]\b/ },
|
|
14332
|
+
{ vendor: "openai", family: "gpt-4o", regex: /\b(gpt-4o|gpt4o|4o)\b/ },
|
|
14333
|
+
{ vendor: "openai", family: "gpt-4", regex: /\b(gpt-4)\b/ },
|
|
14334
|
+
{ vendor: "openai", family: "gpt-3.5", regex: /\b(gpt-3-5|gpt-3\.5|gpt35)\b/ },
|
|
14335
|
+
// Google
|
|
14336
|
+
{ vendor: "google", family: "gemini-pro", regex: /\bgemini.*\bpro\b/ },
|
|
14337
|
+
{ vendor: "google", family: "gemini-flash", regex: /\bgemini.*\bflash\b/ },
|
|
14338
|
+
{ vendor: "google", family: "gemini", regex: /\bgemini\b/ },
|
|
14339
|
+
// Meta
|
|
14340
|
+
{ vendor: "meta", family: "llama-3", regex: /\bllama-?3\b/ },
|
|
14341
|
+
{ vendor: "meta", family: "llama-2", regex: /\bllama-?2\b/ },
|
|
14342
|
+
// Qwen — version is in the family name
|
|
14343
|
+
{ vendor: "qwen", family: "qwen-3", regex: /\bqwen-?3\b/ },
|
|
14344
|
+
{ vendor: "qwen", family: "qwen-2.5", regex: /\bqwen-?2-?5\b/ },
|
|
14345
|
+
{ vendor: "qwen", family: "qwen-2", regex: /\bqwen-?2\b/ },
|
|
14346
|
+
// Mistral
|
|
14347
|
+
{ vendor: "mistral", family: "mixtral", regex: /\bmixtral\b/ },
|
|
14348
|
+
{ vendor: "mistral", family: "codestral", regex: /\bcodestral\b/ },
|
|
14349
|
+
{ vendor: "mistral", family: "mistral", regex: /\bmistral\b/ }
|
|
14350
|
+
];
|
|
14351
|
+
var QUIRK_PATTERNS = [
|
|
14352
|
+
{ regex: /\b(embedding|embed)\b/, quirk: "embedding" },
|
|
14353
|
+
{ regex: /\b(thinking|reasoning)\b/, quirk: "thinking" },
|
|
14354
|
+
{ regex: /\bvision\b/, quirk: "vision" },
|
|
14355
|
+
{ regex: /\b(coder|code)\b/, quirk: "coder" },
|
|
14356
|
+
{ regex: /\binstruct\b/, quirk: "instruct" },
|
|
14357
|
+
{ regex: /\b(mini|nano|tiny|small|lite)\b/, quirk: "small" },
|
|
14358
|
+
{ regex: /\b(large|xl|big|maxi)\b/, quirk: "large" },
|
|
14359
|
+
{ regex: /\bhigh\b/, quirk: "high-variant" },
|
|
14360
|
+
{ regex: /\b(\d+)b\b/, quirk: "sized-suffix" },
|
|
14361
|
+
// 7b, 70b, 405b
|
|
14362
|
+
{ regex: /\b\d{8}\b/, quirk: "dated" }
|
|
14363
|
+
// 20240806 etc
|
|
14364
|
+
];
|
|
14365
|
+
async function resolveModelIdentity(adapter, options = {}) {
|
|
14366
|
+
const rawModelId = adapter.modelId;
|
|
14367
|
+
const hints = options.hints ?? {};
|
|
14368
|
+
let probe;
|
|
14369
|
+
if (options.skipProbe !== true && typeof adapter.listModels === "function") {
|
|
14370
|
+
probe = await runProbe(adapter, rawModelId);
|
|
14371
|
+
}
|
|
14372
|
+
const parsed = parseModelId(rawModelId);
|
|
14373
|
+
return mergeIdentity({ rawModelId, hints, probe, parsed });
|
|
14374
|
+
}
|
|
14375
|
+
function resolveModelIdentitySync(modelId, hints) {
|
|
14376
|
+
return mergeIdentity({
|
|
14377
|
+
rawModelId: modelId,
|
|
14378
|
+
hints: hints ?? {},
|
|
14379
|
+
probe: void 0,
|
|
14380
|
+
parsed: parseModelId(modelId)
|
|
14381
|
+
});
|
|
14382
|
+
}
|
|
14383
|
+
function parseModelId(modelId) {
|
|
14384
|
+
const normalised = normaliseModelId(modelId);
|
|
14385
|
+
const vendor = detectVendor(normalised);
|
|
14386
|
+
const family = vendor !== void 0 ? detectFamily(normalised, vendor) : void 0;
|
|
14387
|
+
const version = vendor !== void 0 && family !== void 0 ? extractVersion(normalised, family) : void 0;
|
|
14388
|
+
const quirks = detectQuirks(normalised);
|
|
14389
|
+
return {
|
|
14390
|
+
...vendor !== void 0 && { vendor },
|
|
14391
|
+
...family !== void 0 && { family },
|
|
14392
|
+
...version !== void 0 && { version },
|
|
14393
|
+
quirks
|
|
14394
|
+
};
|
|
14395
|
+
}
|
|
14396
|
+
function normaliseModelId(modelId) {
|
|
14397
|
+
return modelId.toLowerCase().replace(/[_/]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
14398
|
+
}
|
|
14399
|
+
function detectVendor(normalised) {
|
|
14400
|
+
for (const { vendor, regex } of VENDOR_PATTERNS) {
|
|
14401
|
+
if (regex.test(normalised)) return vendor;
|
|
14402
|
+
}
|
|
14403
|
+
return void 0;
|
|
14404
|
+
}
|
|
14405
|
+
function detectFamily(normalised, vendor) {
|
|
14406
|
+
for (const fp of FAMILY_PATTERNS) {
|
|
14407
|
+
if (fp.vendor !== vendor) continue;
|
|
14408
|
+
if (fp.regex.test(normalised)) return fp.family;
|
|
14409
|
+
}
|
|
14410
|
+
return void 0;
|
|
14411
|
+
}
|
|
14412
|
+
function extractVersion(normalised, family) {
|
|
14413
|
+
const familyRoot = family.replace(/^claude-|^gemini-|^llama-|^qwen-|^gpt-/, "");
|
|
14414
|
+
const idx = normalised.indexOf(familyRoot);
|
|
14415
|
+
if (idx === -1) return void 0;
|
|
14416
|
+
const tail = normalised.slice(idx + familyRoot.length);
|
|
14417
|
+
const m = /^[-]?(\d[\d.\-]*)/.exec(tail);
|
|
14418
|
+
if (m === null) return void 0;
|
|
14419
|
+
return m[1]?.replace(/-+$/, "") ?? void 0;
|
|
14420
|
+
}
|
|
14421
|
+
function detectQuirks(normalised) {
|
|
14422
|
+
const out = [];
|
|
14423
|
+
for (const { regex, quirk } of QUIRK_PATTERNS) {
|
|
14424
|
+
if (regex.test(normalised) && !out.includes(quirk)) out.push(quirk);
|
|
14425
|
+
}
|
|
14426
|
+
return out;
|
|
14427
|
+
}
|
|
14428
|
+
async function runProbe(adapter, modelId) {
|
|
14429
|
+
try {
|
|
14430
|
+
const capable = adapter;
|
|
14431
|
+
const models = await capable.listModels();
|
|
14432
|
+
const matched = models.find((m) => m.id === modelId);
|
|
14433
|
+
if (matched === void 0) return void 0;
|
|
14434
|
+
const result = { metadata: matched };
|
|
14435
|
+
if (matched.ownedBy !== void 0) {
|
|
14436
|
+
const vendor = vendorFromOwnedBy(matched.ownedBy);
|
|
14437
|
+
if (vendor !== void 0) {
|
|
14438
|
+
return { ...result, vendor };
|
|
14439
|
+
}
|
|
14440
|
+
}
|
|
14441
|
+
return result;
|
|
14442
|
+
} catch {
|
|
14443
|
+
return void 0;
|
|
14444
|
+
}
|
|
14445
|
+
}
|
|
14446
|
+
var OWNED_BY_PATTERNS = [
|
|
14447
|
+
{ substr: "anthropic", vendor: "anthropic" },
|
|
14448
|
+
{ substr: "openai", vendor: "openai" },
|
|
14449
|
+
{ substr: "google", vendor: "google" },
|
|
14450
|
+
{ substr: "meta", vendor: "meta" },
|
|
14451
|
+
{ substr: "alibaba", vendor: "qwen" },
|
|
14452
|
+
{ substr: "qwen", vendor: "qwen" },
|
|
14453
|
+
{ substr: "nvidia", vendor: "nvidia" },
|
|
14454
|
+
{ substr: "nemotron", vendor: "nvidia" },
|
|
14455
|
+
{ substr: "mistral", vendor: "mistral" },
|
|
14456
|
+
{ substr: "cohere", vendor: "cohere" },
|
|
14457
|
+
{ substr: "deepseek", vendor: "deepseek" }
|
|
14458
|
+
];
|
|
14459
|
+
function vendorFromOwnedBy(ownedBy) {
|
|
14460
|
+
const lc = ownedBy.toLowerCase();
|
|
14461
|
+
for (const { substr, vendor } of OWNED_BY_PATTERNS) {
|
|
14462
|
+
if (lc.includes(substr)) return vendor;
|
|
14463
|
+
}
|
|
14464
|
+
return void 0;
|
|
14465
|
+
}
|
|
14466
|
+
function mergeIdentity(args) {
|
|
14467
|
+
const { rawModelId, hints, probe, parsed } = args;
|
|
14468
|
+
const version = pickVersion(hints, parsed);
|
|
14469
|
+
return {
|
|
14470
|
+
vendor: hints.vendor ?? probe?.vendor ?? parsed.vendor ?? "unknown",
|
|
14471
|
+
family: hints.family ?? parsed.family ?? "unknown",
|
|
14472
|
+
...version !== void 0 && { version },
|
|
14473
|
+
quirks: [.../* @__PURE__ */ new Set([...hints.quirks ?? [], ...parsed.quirks])],
|
|
14474
|
+
source: pickSource(hints, probe, parsed),
|
|
14475
|
+
rawModelId
|
|
14476
|
+
};
|
|
14477
|
+
}
|
|
14478
|
+
function pickVersion(hints, parsed) {
|
|
14479
|
+
return hints.version ?? parsed.version;
|
|
14480
|
+
}
|
|
14481
|
+
function pickSource(hints, probe, parsed) {
|
|
14482
|
+
if (hints.vendor !== void 0) return "modelHints";
|
|
14483
|
+
if (probe?.vendor !== void 0) return "probe";
|
|
14484
|
+
if (parsed.vendor !== void 0) return "modelIdParse";
|
|
14485
|
+
return "default";
|
|
14486
|
+
}
|
|
14487
|
+
|
|
14488
|
+
// src/config/model-behavior-profile.ts
|
|
14489
|
+
var DEFAULT_PROFILE = {
|
|
14490
|
+
parallelToolCalls: false,
|
|
14491
|
+
promptCaching: "none",
|
|
14492
|
+
toolDefinitionFormat: "openai",
|
|
14493
|
+
maxRecommendedTurnBudget: 10,
|
|
14494
|
+
strictJson: true,
|
|
14495
|
+
quirks: [],
|
|
14496
|
+
profileId: "default"
|
|
14497
|
+
};
|
|
14498
|
+
var VENDOR_PROFILES = {
|
|
14499
|
+
anthropic: {
|
|
14500
|
+
profileId: "anthropic-default",
|
|
14501
|
+
promptCaching: "ephemeral",
|
|
14502
|
+
toolDefinitionFormat: "anthropic",
|
|
14503
|
+
parallelToolCalls: true,
|
|
14504
|
+
// Claude 4.x supports parallel tool_use blocks
|
|
14505
|
+
maxRecommendedTurnBudget: 15
|
|
14506
|
+
},
|
|
14507
|
+
openai: {
|
|
14508
|
+
profileId: "openai-default",
|
|
14509
|
+
parallelToolCalls: true,
|
|
14510
|
+
toolDefinitionFormat: "openai",
|
|
14511
|
+
maxRecommendedTurnBudget: 15
|
|
14512
|
+
},
|
|
14513
|
+
google: {
|
|
14514
|
+
profileId: "google-default",
|
|
14515
|
+
toolDefinitionFormat: "gemini",
|
|
14516
|
+
parallelToolCalls: true,
|
|
14517
|
+
maxRecommendedTurnBudget: 15
|
|
14518
|
+
},
|
|
14519
|
+
meta: {
|
|
14520
|
+
profileId: "meta-default",
|
|
14521
|
+
toolDefinitionFormat: "openai",
|
|
14522
|
+
parallelToolCalls: false,
|
|
14523
|
+
// many open-weight Llamas struggle with parallel tools
|
|
14524
|
+
maxRecommendedTurnBudget: 8
|
|
14525
|
+
},
|
|
14526
|
+
qwen: {
|
|
14527
|
+
profileId: "qwen-default",
|
|
14528
|
+
toolDefinitionFormat: "openai",
|
|
14529
|
+
parallelToolCalls: false,
|
|
14530
|
+
maxRecommendedTurnBudget: 8
|
|
14531
|
+
},
|
|
14532
|
+
nvidia: {
|
|
14533
|
+
profileId: "nvidia-nemotron-default",
|
|
14534
|
+
toolDefinitionFormat: "openai",
|
|
14535
|
+
parallelToolCalls: false,
|
|
14536
|
+
maxRecommendedTurnBudget: 8
|
|
14537
|
+
},
|
|
14538
|
+
mistral: {
|
|
14539
|
+
profileId: "mistral-default",
|
|
14540
|
+
toolDefinitionFormat: "openai",
|
|
14541
|
+
parallelToolCalls: false,
|
|
14542
|
+
maxRecommendedTurnBudget: 8
|
|
14543
|
+
},
|
|
14544
|
+
cohere: {
|
|
14545
|
+
profileId: "cohere-default",
|
|
14546
|
+
toolDefinitionFormat: "openai",
|
|
14547
|
+
parallelToolCalls: false,
|
|
14548
|
+
maxRecommendedTurnBudget: 8
|
|
14549
|
+
},
|
|
14550
|
+
deepseek: {
|
|
14551
|
+
profileId: "deepseek-default",
|
|
14552
|
+
toolDefinitionFormat: "openai",
|
|
14553
|
+
parallelToolCalls: false,
|
|
14554
|
+
maxRecommendedTurnBudget: 10
|
|
14555
|
+
}
|
|
14556
|
+
};
|
|
14557
|
+
var FAMILY_PROFILES = [
|
|
14558
|
+
{
|
|
14559
|
+
vendor: "anthropic",
|
|
14560
|
+
family: "claude-opus",
|
|
14561
|
+
override: { profileId: "claude-opus", maxRecommendedTurnBudget: 20 }
|
|
14562
|
+
},
|
|
14563
|
+
{
|
|
14564
|
+
vendor: "anthropic",
|
|
14565
|
+
family: "claude-haiku",
|
|
14566
|
+
override: { profileId: "claude-haiku", maxRecommendedTurnBudget: 8 }
|
|
14567
|
+
},
|
|
14568
|
+
{
|
|
14569
|
+
vendor: "openai",
|
|
14570
|
+
family: "o-reasoning",
|
|
14571
|
+
override: {
|
|
14572
|
+
profileId: "openai-o-reasoning",
|
|
14573
|
+
// o1-style reasoning models burn extra turns thinking; recommend
|
|
14574
|
+
// a higher budget. They also don't support `temperature`.
|
|
14575
|
+
maxRecommendedTurnBudget: 25
|
|
14576
|
+
}
|
|
14577
|
+
},
|
|
14578
|
+
{
|
|
14579
|
+
vendor: "google",
|
|
14580
|
+
family: "gemini-flash",
|
|
14581
|
+
override: { profileId: "gemini-flash", maxRecommendedTurnBudget: 8 }
|
|
14582
|
+
}
|
|
14583
|
+
];
|
|
14584
|
+
function lookupModelProfile(identity) {
|
|
14585
|
+
let profile = { ...DEFAULT_PROFILE };
|
|
14586
|
+
const vendorOverride = VENDOR_PROFILES[identity.vendor];
|
|
14587
|
+
if (vendorOverride !== void 0) profile = mergeProfile(profile, vendorOverride);
|
|
14588
|
+
const familyOverride = FAMILY_PROFILES.find(
|
|
14589
|
+
(e) => e.vendor === identity.vendor && e.family === identity.family
|
|
14590
|
+
);
|
|
14591
|
+
if (familyOverride !== void 0) profile = mergeProfile(profile, familyOverride.override);
|
|
14592
|
+
profile = applyQuirkOverlay(profile, identity.quirks);
|
|
14593
|
+
return profile;
|
|
14594
|
+
}
|
|
14595
|
+
function mergeProfile(base, override) {
|
|
14596
|
+
return {
|
|
14597
|
+
...base,
|
|
14598
|
+
...override
|
|
14599
|
+
};
|
|
14600
|
+
}
|
|
14601
|
+
function applyQuirkOverlay(profile, identityQuirks) {
|
|
14602
|
+
if (identityQuirks.length === 0) return profile;
|
|
14603
|
+
const merged = /* @__PURE__ */ new Set([...profile.quirks, ...identityQuirks]);
|
|
14604
|
+
let maxBudget = profile.maxRecommendedTurnBudget;
|
|
14605
|
+
if (identityQuirks.includes("thinking")) {
|
|
14606
|
+
maxBudget = Math.ceil(maxBudget * 1.5);
|
|
14607
|
+
}
|
|
14608
|
+
return {
|
|
14609
|
+
...profile,
|
|
14610
|
+
quirks: [...merged],
|
|
14611
|
+
maxRecommendedTurnBudget: maxBudget
|
|
14612
|
+
};
|
|
14613
|
+
}
|
|
14614
|
+
|
|
14615
|
+
// src/agents/agentic/types.ts
|
|
14616
|
+
var AgentError9 = class extends Error {
|
|
14617
|
+
causeData;
|
|
14618
|
+
constructor(message, cause) {
|
|
14619
|
+
super(message);
|
|
14620
|
+
this.name = "AgentError";
|
|
14621
|
+
if (cause !== void 0) this.causeData = cause;
|
|
14622
|
+
}
|
|
14623
|
+
};
|
|
14624
|
+
|
|
14625
|
+
// src/agents/agentic/agentic-adapter.ts
|
|
14626
|
+
var AgenticAdapter = class {
|
|
14627
|
+
providerId;
|
|
14628
|
+
modelId;
|
|
14629
|
+
/**
|
|
14630
|
+
* Adapter strategy stamp — composed from the resolved model
|
|
14631
|
+
* identity, NOT the IModelAdapter's providerId. For a custom OpenAI
|
|
14632
|
+
* gateway fronting Claude, this reads `native:anthropic` even though
|
|
14633
|
+
* `IModelAdapter.providerId === 'openai'`.
|
|
14634
|
+
*
|
|
14635
|
+
* Initialised eagerly from the modelId parse (sync); upgraded after
|
|
14636
|
+
* the first `runAgent` if the probe contributes a higher-confidence
|
|
14637
|
+
* vendor signal.
|
|
14638
|
+
*/
|
|
14639
|
+
adapterStrategy;
|
|
14640
|
+
model;
|
|
14641
|
+
options;
|
|
14642
|
+
semaphore;
|
|
14643
|
+
resolvedIdentity;
|
|
14644
|
+
profile;
|
|
14645
|
+
profileResolutionPromise = null;
|
|
14646
|
+
constructor(modelAdapter, options = {}) {
|
|
14647
|
+
this.model = modelAdapter;
|
|
14648
|
+
this.options = options;
|
|
14649
|
+
this.providerId = modelAdapter.providerId;
|
|
14650
|
+
this.modelId = modelAdapter.modelId;
|
|
14651
|
+
this.resolvedIdentity = resolveModelIdentitySync(modelAdapter.modelId, options.modelHints);
|
|
14652
|
+
this.profile = options.forceProfile ?? lookupModelProfile(this.resolvedIdentity);
|
|
14653
|
+
this.adapterStrategy = stampStrategy(this.resolvedIdentity);
|
|
14654
|
+
if (this.profile.quirks.includes("embedding")) {
|
|
14655
|
+
throw new AgentError9(
|
|
14656
|
+
`Refusing to construct AgenticAdapter for an embedding model (${modelAdapter.modelId}). Agentic loops require a chat-completion model.`
|
|
14657
|
+
);
|
|
14658
|
+
}
|
|
14659
|
+
this.semaphore = options.maxConcurrent !== void 0 && options.maxConcurrent > 0 ? new Semaphore(options.maxConcurrent) : null;
|
|
14660
|
+
}
|
|
14661
|
+
/**
|
|
14662
|
+
* Read-only accessor for the resolved profile. Mostly used in tests
|
|
14663
|
+
* + observability surfaces; production callers shouldn't need this.
|
|
14664
|
+
*/
|
|
14665
|
+
getProfile() {
|
|
14666
|
+
return this.profile;
|
|
14667
|
+
}
|
|
14668
|
+
/**
|
|
14669
|
+
* Read-only accessor for the resolved identity. After the first
|
|
14670
|
+
* `runAgent` call (if a probe ran), this may differ from what the
|
|
14671
|
+
* sync constructor stored — useful for audit logs.
|
|
14672
|
+
*/
|
|
14673
|
+
getResolvedIdentity() {
|
|
14674
|
+
return this.resolvedIdentity;
|
|
14675
|
+
}
|
|
14676
|
+
/**
|
|
14677
|
+
* Lazily resolve identity via the async probe + refresh the profile.
|
|
14678
|
+
* Idempotent + concurrent-call-safe (multiple `runAgent`s share the
|
|
14679
|
+
* same in-flight resolution).
|
|
14680
|
+
*/
|
|
14681
|
+
async ensureIdentityResolved() {
|
|
14682
|
+
if (this.options.forceProfile !== void 0) return;
|
|
14683
|
+
if (this.options.skipProbe === true) return;
|
|
14684
|
+
if (typeof this.model.listModels !== "function") return;
|
|
14685
|
+
if (this.profileResolutionPromise !== null) {
|
|
14686
|
+
await this.profileResolutionPromise;
|
|
14687
|
+
return;
|
|
14688
|
+
}
|
|
14689
|
+
this.profileResolutionPromise = this.doResolveIdentity();
|
|
14690
|
+
try {
|
|
14691
|
+
await this.profileResolutionPromise;
|
|
14692
|
+
} finally {
|
|
14693
|
+
}
|
|
14694
|
+
}
|
|
14695
|
+
/**
|
|
14696
|
+
* If the resolved profile asks for `'ephemeral'` prompt caching,
|
|
14697
|
+
* mark the LAST tool definition with `cache_control: { type:
|
|
14698
|
+
* 'ephemeral' }`. Anthropic interprets this as "cache everything up
|
|
14699
|
+
* to and including the tool definitions"; other providers strip the
|
|
14700
|
+
* unknown field at the canonical-request mapper.
|
|
14701
|
+
*
|
|
14702
|
+
* Last-tool placement is the Anthropic convention: cache key is the
|
|
14703
|
+
* prefix, so caching the final tool block caches the entire tools
|
|
14704
|
+
* section. Per-turn the system prompt + user prompt + tools are
|
|
14705
|
+
* stable, so cache-hit rate on multi-turn agent runs is high.
|
|
14706
|
+
*/
|
|
14707
|
+
applyCacheControlIfRequested(tools) {
|
|
14708
|
+
if (this.profile.promptCaching !== "ephemeral") return [...tools];
|
|
14709
|
+
if (tools.length === 0) return [];
|
|
14710
|
+
return tools.map(
|
|
14711
|
+
(tool, idx) => idx === tools.length - 1 ? {
|
|
14712
|
+
...tool,
|
|
14713
|
+
cacheControl: { type: "ephemeral" }
|
|
14714
|
+
} : tool
|
|
14715
|
+
);
|
|
14716
|
+
}
|
|
14717
|
+
async doResolveIdentity() {
|
|
14718
|
+
const refined = await resolveModelIdentity(this.model, {
|
|
14719
|
+
...this.options.modelHints !== void 0 && { hints: this.options.modelHints }
|
|
14720
|
+
});
|
|
14721
|
+
if (refined.source === "probe" || refined.source === "modelHints") {
|
|
14722
|
+
this.resolvedIdentity = refined;
|
|
14723
|
+
this.profile = lookupModelProfile(refined);
|
|
14724
|
+
this.adapterStrategy = stampStrategy(refined);
|
|
14725
|
+
}
|
|
14726
|
+
}
|
|
14727
|
+
async runAgent(args) {
|
|
14728
|
+
await this.ensureIdentityResolved();
|
|
14729
|
+
const turnBudget = args.turnBudget ?? this.profile.maxRecommendedTurnBudget;
|
|
14730
|
+
if (turnBudget <= 0) {
|
|
14731
|
+
return err(new AgentError9(`turnBudget must be > 0, got ${String(turnBudget)}`));
|
|
14732
|
+
}
|
|
14733
|
+
const resolvedArgs = { ...args, turnBudget };
|
|
14734
|
+
const state = {
|
|
14735
|
+
turns: [],
|
|
14736
|
+
totalInputTokens: 0,
|
|
14737
|
+
totalOutputTokens: 0,
|
|
14738
|
+
finalContent: "",
|
|
14739
|
+
messages: [{ role: "user", content: args.userPrompt }]
|
|
14740
|
+
};
|
|
14741
|
+
while (state.turns.length < turnBudget) {
|
|
14742
|
+
if (args.signal?.aborted === true) {
|
|
14743
|
+
return ok(this.buildFromState(state, "cancelled"));
|
|
14744
|
+
}
|
|
14745
|
+
const turnOutcome = await this.runOneTurn(resolvedArgs, state);
|
|
14746
|
+
if (turnOutcome.kind === "error") return err(turnOutcome.error);
|
|
14747
|
+
if (turnOutcome.kind === "stop") {
|
|
14748
|
+
return ok(this.buildFromState(state, turnOutcome.reason));
|
|
14749
|
+
}
|
|
14750
|
+
}
|
|
14751
|
+
return ok(this.buildFromState(state, "turn-budget"));
|
|
14752
|
+
}
|
|
14753
|
+
/**
|
|
14754
|
+
* Run one model-call cycle: call → check for tool_use → execute tool
|
|
14755
|
+
* calls → append results. Returns one of three outcomes describing
|
|
14756
|
+
* whether the loop continues, stops naturally, or hit a model error.
|
|
14757
|
+
*/
|
|
14758
|
+
async runOneTurn(args, state) {
|
|
14759
|
+
const t0 = Date.now();
|
|
14760
|
+
const completion = await this.callModelGated({
|
|
14761
|
+
messages: state.messages,
|
|
14762
|
+
systemPrompt: args.systemPrompt,
|
|
14763
|
+
tools: this.applyCacheControlIfRequested([...args.tools]),
|
|
14764
|
+
...args.temperature !== void 0 && { temperature: args.temperature },
|
|
14765
|
+
...args.maxTokens !== void 0 && { maxTokens: args.maxTokens }
|
|
14766
|
+
});
|
|
14767
|
+
const modelLatencyMs = Date.now() - t0;
|
|
14768
|
+
if (!completion.ok) {
|
|
14769
|
+
return {
|
|
14770
|
+
kind: "error",
|
|
14771
|
+
error: new AgentError9(
|
|
14772
|
+
`Model call failed at turn ${String(state.turns.length)}: ${completion.error.message}`,
|
|
14773
|
+
completion.error
|
|
14774
|
+
)
|
|
14775
|
+
};
|
|
14776
|
+
}
|
|
14777
|
+
const response = completion.value;
|
|
14778
|
+
state.totalInputTokens += response.usage.inputTokens;
|
|
14779
|
+
state.totalOutputTokens += response.usage.outputTokens;
|
|
14780
|
+
const toolUses = response.content.filter(
|
|
14781
|
+
(c) => c.type === "tool_use"
|
|
14782
|
+
);
|
|
14783
|
+
if (toolUses.length === 0) {
|
|
14784
|
+
state.finalContent = extractFinalText(response.content);
|
|
14785
|
+
return { kind: "stop", reason: "agent-stopped" };
|
|
14786
|
+
}
|
|
14787
|
+
state.messages.push({ role: "assistant", content: response.content });
|
|
14788
|
+
return this.processToolCalls(args, state, toolUses, response, modelLatencyMs);
|
|
14789
|
+
}
|
|
14790
|
+
async processToolCalls(args, state, toolUses, response, modelLatencyMs) {
|
|
14791
|
+
if (this.profile.parallelToolCalls && toolUses.length > 1) {
|
|
14792
|
+
return this.processToolCallsParallel(args, state, toolUses, response, modelLatencyMs);
|
|
14793
|
+
}
|
|
14794
|
+
return this.processToolCallsSequential(args, state, toolUses, response, modelLatencyMs);
|
|
14795
|
+
}
|
|
14796
|
+
async processToolCallsSequential(args, state, toolUses, response, modelLatencyMs) {
|
|
14797
|
+
const toolResultBlocks = [];
|
|
14798
|
+
for (const toolUse of toolUses) {
|
|
14799
|
+
if (state.turns.length >= args.turnBudget) break;
|
|
14800
|
+
const outcome = await this.invokeToolAndRecord(
|
|
14801
|
+
args,
|
|
14802
|
+
state,
|
|
14803
|
+
toolUse,
|
|
14804
|
+
response,
|
|
14805
|
+
modelLatencyMs
|
|
14806
|
+
);
|
|
14807
|
+
if (outcome.kind === "stop") return outcome;
|
|
14808
|
+
toolResultBlocks.push(outcome.toolResultBlock);
|
|
14809
|
+
}
|
|
14810
|
+
if (toolResultBlocks.length > 0) {
|
|
14811
|
+
state.messages.push({ role: "user", content: toolResultBlocks });
|
|
14812
|
+
}
|
|
14813
|
+
return { kind: "continue" };
|
|
14814
|
+
}
|
|
14815
|
+
/**
|
|
14816
|
+
* Profile-driven parallel tool execution. Used when
|
|
14817
|
+
* `profile.parallelToolCalls === true` AND the model emitted >1
|
|
14818
|
+
* tool_use block in a single turn.
|
|
14819
|
+
*
|
|
14820
|
+
* Each tool call still produces its own `AgentTurn`; turn-budget
|
|
14821
|
+
* applies to the post-completion count (we don't pre-cap the
|
|
14822
|
+
* Promise.all because the model already issued all calls — better
|
|
14823
|
+
* to record everything and let the next turn be the budget breaker).
|
|
14824
|
+
*/
|
|
14825
|
+
async processToolCallsParallel(args, state, toolUses, response, modelLatencyMs) {
|
|
14826
|
+
const startIndex = state.turns.length;
|
|
14827
|
+
const promises2 = toolUses.map(
|
|
14828
|
+
(toolUse, offset) => this.invokeToolForParallel(args, toolUse, response, modelLatencyMs, startIndex + offset)
|
|
14829
|
+
);
|
|
14830
|
+
const outcomes = await Promise.all(promises2);
|
|
14831
|
+
const toolResultBlocks = [];
|
|
14832
|
+
for (const outcome of outcomes) {
|
|
14833
|
+
if (outcome.kind === "stop-tool-error") {
|
|
14834
|
+
state.turns.push(outcome.turn);
|
|
14835
|
+
args.onTurn?.(outcome.turn);
|
|
14836
|
+
return { kind: "stop", reason: "tool-error" };
|
|
14837
|
+
}
|
|
14838
|
+
state.turns.push(outcome.turn);
|
|
14839
|
+
args.onTurn?.(outcome.turn);
|
|
14840
|
+
toolResultBlocks.push(outcome.toolResultBlock);
|
|
14841
|
+
}
|
|
14842
|
+
if (toolResultBlocks.length > 0) {
|
|
14843
|
+
state.messages.push({ role: "user", content: toolResultBlocks });
|
|
14844
|
+
}
|
|
14845
|
+
return { kind: "continue" };
|
|
14846
|
+
}
|
|
14847
|
+
/**
|
|
14848
|
+
* Per-call wrapper used by parallel execution. Returns a captured
|
|
14849
|
+
* outcome (turn + result-block, OR turn + tool-error flag) without
|
|
14850
|
+
* touching shared state — `processToolCallsParallel` reduces the
|
|
14851
|
+
* outcomes deterministically afterwards.
|
|
14852
|
+
*/
|
|
14853
|
+
async invokeToolForParallel(args, toolUse, response, modelLatencyMs, turnIndex) {
|
|
14854
|
+
const toolCall = {
|
|
14855
|
+
id: toolUse.id,
|
|
14856
|
+
name: toolUse.name,
|
|
14857
|
+
arguments: toolUse.input
|
|
14858
|
+
};
|
|
14859
|
+
const tt0 = Date.now();
|
|
14860
|
+
try {
|
|
14861
|
+
const toolResult = await args.onToolCall(toolCall);
|
|
14862
|
+
const turn = buildTurn({
|
|
14863
|
+
turnIndex,
|
|
14864
|
+
toolCall,
|
|
14865
|
+
toolResult,
|
|
14866
|
+
modelLatencyMs,
|
|
14867
|
+
toolLatencyMs: Date.now() - tt0,
|
|
14868
|
+
response
|
|
14869
|
+
});
|
|
14870
|
+
return {
|
|
14871
|
+
kind: "recorded",
|
|
14872
|
+
turn,
|
|
14873
|
+
toolResultBlock: {
|
|
14874
|
+
type: "tool_result",
|
|
14875
|
+
tool_use_id: toolUse.id,
|
|
14876
|
+
content: toolResult.content,
|
|
14877
|
+
...toolResult.isError === true && { is_error: true }
|
|
14878
|
+
}
|
|
14879
|
+
};
|
|
14880
|
+
} catch (caught) {
|
|
14881
|
+
const turn = buildTurn({
|
|
14882
|
+
turnIndex,
|
|
14883
|
+
toolCall,
|
|
14884
|
+
toolResult: {
|
|
14885
|
+
content: caught instanceof Error ? caught.message : String(caught),
|
|
14886
|
+
isError: true
|
|
14887
|
+
},
|
|
14888
|
+
modelLatencyMs,
|
|
14889
|
+
toolLatencyMs: Date.now() - tt0,
|
|
14890
|
+
response
|
|
14891
|
+
});
|
|
14892
|
+
return { kind: "stop-tool-error", turn };
|
|
14893
|
+
}
|
|
14894
|
+
}
|
|
14895
|
+
async invokeToolAndRecord(args, state, toolUse, response, modelLatencyMs) {
|
|
14896
|
+
const toolCall = {
|
|
14897
|
+
id: toolUse.id,
|
|
14898
|
+
name: toolUse.name,
|
|
14899
|
+
arguments: toolUse.input
|
|
14900
|
+
};
|
|
14901
|
+
const tt0 = Date.now();
|
|
14902
|
+
try {
|
|
14903
|
+
const toolResult = await args.onToolCall(toolCall);
|
|
14904
|
+
return recordToolSuccess({
|
|
14905
|
+
args,
|
|
14906
|
+
state,
|
|
14907
|
+
toolUse,
|
|
14908
|
+
toolCall,
|
|
14909
|
+
toolResult,
|
|
14910
|
+
modelLatencyMs,
|
|
14911
|
+
toolLatencyMs: Date.now() - tt0,
|
|
14912
|
+
response
|
|
14913
|
+
});
|
|
14914
|
+
} catch (caught) {
|
|
14915
|
+
const errTurn = buildTurn({
|
|
14916
|
+
turnIndex: state.turns.length,
|
|
14917
|
+
toolCall,
|
|
14918
|
+
toolResult: {
|
|
14919
|
+
content: caught instanceof Error ? caught.message : String(caught),
|
|
14920
|
+
isError: true
|
|
14921
|
+
},
|
|
14922
|
+
modelLatencyMs,
|
|
14923
|
+
toolLatencyMs: Date.now() - tt0,
|
|
14924
|
+
response
|
|
14925
|
+
});
|
|
14926
|
+
state.turns.push(errTurn);
|
|
14927
|
+
args.onTurn?.(errTurn);
|
|
14928
|
+
return { kind: "stop", reason: "tool-error" };
|
|
14929
|
+
}
|
|
14930
|
+
}
|
|
14931
|
+
buildFromState(state, stopReason) {
|
|
14932
|
+
return this.buildResult(
|
|
14933
|
+
state.turns,
|
|
14934
|
+
state.totalInputTokens,
|
|
14935
|
+
state.totalOutputTokens,
|
|
14936
|
+
stopReason,
|
|
14937
|
+
state.finalContent
|
|
14938
|
+
);
|
|
14939
|
+
}
|
|
14940
|
+
/**
|
|
14941
|
+
* Wrap `model.complete` in an optional concurrency gate. The
|
|
14942
|
+
* semaphore is held only across the model API call — released
|
|
14943
|
+
* before tool execution so harnesses doing slow tool calls don't
|
|
14944
|
+
* starve other concurrent `runAgent` calls.
|
|
14945
|
+
*/
|
|
14946
|
+
async callModelGated(request) {
|
|
14947
|
+
if (this.semaphore === null) {
|
|
14948
|
+
return this.model.complete(request);
|
|
14949
|
+
}
|
|
14950
|
+
await this.semaphore.acquire();
|
|
14951
|
+
try {
|
|
14952
|
+
return await this.model.complete(request);
|
|
14953
|
+
} finally {
|
|
14954
|
+
this.semaphore.release();
|
|
14955
|
+
}
|
|
14956
|
+
}
|
|
14957
|
+
buildResult(turns, totalInputTokens, totalOutputTokens, stopReason, finalContent) {
|
|
14958
|
+
return {
|
|
14959
|
+
turnsUsed: turns.length,
|
|
14960
|
+
stopReason,
|
|
14961
|
+
turns,
|
|
14962
|
+
...totalInputTokens > 0 && { totalInputTokens },
|
|
14963
|
+
...totalOutputTokens > 0 && { totalOutputTokens },
|
|
14964
|
+
providerId: this.providerId,
|
|
14965
|
+
modelId: this.modelId,
|
|
14966
|
+
adapterStrategy: this.adapterStrategy,
|
|
14967
|
+
finalContent
|
|
14968
|
+
};
|
|
14969
|
+
}
|
|
14970
|
+
};
|
|
14971
|
+
function stampStrategy(identity) {
|
|
14972
|
+
return identity.vendor === "unknown" ? "wrapper" : `native:${identity.vendor}`;
|
|
14973
|
+
}
|
|
14974
|
+
function recordToolSuccess(p) {
|
|
14975
|
+
const turn = buildTurn({
|
|
14976
|
+
turnIndex: p.state.turns.length,
|
|
14977
|
+
toolCall: p.toolCall,
|
|
14978
|
+
toolResult: p.toolResult,
|
|
14979
|
+
modelLatencyMs: p.modelLatencyMs,
|
|
14980
|
+
toolLatencyMs: p.toolLatencyMs,
|
|
14981
|
+
response: p.response
|
|
14982
|
+
});
|
|
14983
|
+
p.state.turns.push(turn);
|
|
14984
|
+
p.args.onTurn?.(turn);
|
|
14985
|
+
return {
|
|
14986
|
+
kind: "recorded",
|
|
14987
|
+
toolResultBlock: {
|
|
14988
|
+
type: "tool_result",
|
|
14989
|
+
tool_use_id: p.toolUse.id,
|
|
14990
|
+
content: p.toolResult.content,
|
|
14991
|
+
...p.toolResult.isError === true && { is_error: true }
|
|
14992
|
+
}
|
|
14993
|
+
};
|
|
14994
|
+
}
|
|
14995
|
+
function buildTurn(b) {
|
|
14996
|
+
return {
|
|
14997
|
+
turnIndex: b.turnIndex,
|
|
14998
|
+
toolCall: b.toolCall,
|
|
14999
|
+
toolResult: b.toolResult,
|
|
15000
|
+
modelLatencyMs: b.modelLatencyMs,
|
|
15001
|
+
toolLatencyMs: b.toolLatencyMs,
|
|
15002
|
+
inputTokens: b.response.usage.inputTokens,
|
|
15003
|
+
outputTokens: b.response.usage.outputTokens
|
|
15004
|
+
};
|
|
15005
|
+
}
|
|
15006
|
+
function extractFinalText(content) {
|
|
15007
|
+
return content.filter((c) => c.type === "text").map((c) => c.text).join("\n").trim();
|
|
15008
|
+
}
|
|
15009
|
+
var Semaphore = class {
|
|
15010
|
+
waiters = [];
|
|
15011
|
+
available;
|
|
15012
|
+
constructor(capacity) {
|
|
15013
|
+
this.available = capacity;
|
|
15014
|
+
}
|
|
15015
|
+
acquire() {
|
|
15016
|
+
if (this.available > 0) {
|
|
15017
|
+
this.available -= 1;
|
|
15018
|
+
return Promise.resolve();
|
|
15019
|
+
}
|
|
15020
|
+
return new Promise((resolve19) => {
|
|
15021
|
+
this.waiters.push(resolve19);
|
|
15022
|
+
});
|
|
15023
|
+
}
|
|
15024
|
+
release() {
|
|
15025
|
+
const next = this.waiters.shift();
|
|
15026
|
+
if (next !== void 0) {
|
|
15027
|
+
next();
|
|
15028
|
+
return;
|
|
15029
|
+
}
|
|
15030
|
+
this.available += 1;
|
|
15031
|
+
}
|
|
15032
|
+
};
|
|
15033
|
+
|
|
15034
|
+
// src/agents/agentic/factory.ts
|
|
15035
|
+
function createAgenticAdapter(modelAdapter, options = {}) {
|
|
15036
|
+
return new AgenticAdapter(modelAdapter, options);
|
|
15037
|
+
}
|
|
15038
|
+
|
|
14312
15039
|
// src/agents/reasoning/forest-node-types.ts
|
|
14313
15040
|
import { z as z20 } from "zod";
|
|
14314
15041
|
var NodeStateSchema = z20.enum(["pending", "active", "completed", "pruned", "error"]);
|
|
@@ -49406,6 +50133,8 @@ export {
|
|
|
49406
50133
|
SkillLoader,
|
|
49407
50134
|
createSkillLoader,
|
|
49408
50135
|
loadAllExternalPacks,
|
|
50136
|
+
AgenticAdapter,
|
|
50137
|
+
createAgenticAdapter,
|
|
49409
50138
|
NodeStateSchema,
|
|
49410
50139
|
ReasoningStepTypeSchema,
|
|
49411
50140
|
ReasoningNodeMetadataSchema,
|
|
@@ -49816,4 +50545,4 @@ export {
|
|
|
49816
50545
|
detectBackend,
|
|
49817
50546
|
createTaskTracker
|
|
49818
50547
|
};
|
|
49819
|
-
//# sourceMappingURL=chunk-
|
|
50548
|
+
//# sourceMappingURL=chunk-J4VR2WNI.js.map
|