agency-lang 0.7.6 → 0.7.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/dist/lib/agents/agency-agent/agent.agency +490 -39
- package/dist/lib/agents/agency-agent/agent.js +3583 -639
- package/dist/lib/agents/agency-agent/lib/attachments.js +6 -3
- package/dist/lib/agents/agency-agent/lib/capabilities.agency +464 -0
- package/dist/lib/agents/agency-agent/lib/capabilities.js +2570 -0
- package/dist/lib/agents/agency-agent/lib/config.agency +22 -1
- package/dist/lib/agents/agency-agent/lib/config.js +159 -6
- package/dist/lib/agents/agency-agent/lib/defaultPolicy.js +8 -4
- package/dist/lib/agents/agency-agent/lib/modelFilters.js +4 -2
- package/dist/lib/agents/agency-agent/lib/models.agency +46 -12
- package/dist/lib/agents/agency-agent/lib/models.js +359 -33
- package/dist/lib/agents/agency-agent/lib/resolution.agency +22 -7
- package/dist/lib/agents/agency-agent/lib/resolution.js +131 -46
- package/dist/lib/agents/agency-agent/lib/search.js +34 -17
- package/dist/lib/agents/agency-agent/lib/settings.agency +27 -4
- package/dist/lib/agents/agency-agent/lib/settings.js +224 -23
- package/dist/lib/agents/agency-agent/lib/slots.js +6 -3
- package/dist/lib/agents/agency-agent/lib/utils.js +16 -8
- package/dist/lib/agents/agency-agent/shared.agency +218 -18
- package/dist/lib/agents/agency-agent/shared.js +1890 -186
- package/dist/lib/agents/agency-agent/subagents/code.agency +45 -1
- package/dist/lib/agents/agency-agent/subagents/code.js +105 -11
- package/dist/lib/agents/agency-agent/subagents/explorer.js +4 -2
- package/dist/lib/agents/agency-agent/subagents/oracle.js +4 -2
- package/dist/lib/agents/agency-agent/subagents/research.js +4 -2
- package/dist/lib/agents/agency-agent/subagents/review.js +20 -10
- package/dist/lib/agents/agency-agent/subagents/verify.agency +103 -0
- package/dist/lib/agents/agency-agent/subagents/verify.js +797 -0
- package/dist/lib/agents/agency-agent/tests/agentDir.agency +20 -0
- package/dist/lib/agents/agency-agent/tests/agentDir.js +353 -0
- package/dist/lib/agents/agency-agent/tests/agentDir.test.json +15 -0
- package/dist/lib/agents/agency-agent/tests/agentTurn.agency +163 -1
- package/dist/lib/agents/agency-agent/tests/agentTurn.js +1433 -141
- package/dist/lib/agents/agency-agent/tests/agentTurn.test.json +261 -19
- package/dist/lib/agents/agency-agent/tests/capabilities.agency +233 -0
- package/dist/lib/agents/agency-agent/tests/capabilities.js +2203 -0
- package/dist/lib/agents/agency-agent/tests/capabilities.test.json +165 -0
- package/dist/lib/agents/agency-agent/tests/execPolicy.js +2 -1
- package/dist/lib/agents/agency-agent/tests/gitPolicy.js +2 -1
- package/dist/lib/agents/agency-agent/tests/memoryWiring.agency +148 -0
- package/dist/lib/agents/agency-agent/tests/memoryWiring.js +1334 -0
- package/dist/lib/agents/agency-agent/tests/memoryWiring.test.json +75 -0
- package/dist/lib/agents/agency-agent/tests/models.js +2 -1
- package/dist/lib/agents/agency-agent/tests/resolution.agency +52 -0
- package/dist/lib/agents/agency-agent/tests/resolution.js +377 -3
- package/dist/lib/agents/agency-agent/tests/resolution.test.json +110 -8
- package/dist/lib/agents/agency-agent/tests/search.js +14 -7
- package/dist/lib/agents/agency-agent/tests/settings.agency +109 -0
- package/dist/lib/agents/agency-agent/tests/settings.js +939 -2
- package/dist/lib/agents/agency-agent/tests/settings.test.json +105 -6
- package/dist/lib/agents/agency-agent/tests/toolWiring.js +2 -1
- package/dist/lib/agents/docs/cli/agent.md +16 -0
- package/dist/lib/agents/docs/guide/error-handling.md +21 -0
- package/dist/lib/agents/docs/guide/types.md +48 -0
- package/dist/lib/agents/policy/agent.js +26 -13
- package/dist/lib/backends/agencyGenerator.test.js +21 -0
- package/dist/lib/backends/recursiveAliases.codegen.test.d.ts +1 -0
- package/dist/lib/backends/recursiveAliases.codegen.test.js +229 -0
- package/dist/lib/backends/typescriptBuilder/nameClassifier.d.ts +6 -0
- package/dist/lib/backends/typescriptBuilder/nameClassifier.js +1 -1
- package/dist/lib/backends/typescriptBuilder.d.ts +14 -0
- package/dist/lib/backends/typescriptBuilder.js +74 -11
- package/dist/lib/backends/typescriptGenerator/recursiveSchemaJson.test.d.ts +1 -0
- package/dist/lib/backends/typescriptGenerator/recursiveSchemaJson.test.js +32 -0
- package/dist/lib/backends/typescriptGenerator/typeToZodSchema.d.ts +1 -1
- package/dist/lib/backends/typescriptGenerator/typeToZodSchema.js +19 -7
- package/dist/lib/backends/typescriptGenerator/validationDescriptor.d.ts +1 -1
- package/dist/lib/backends/typescriptGenerator/validationDescriptor.js +30 -20
- package/dist/lib/backends/valueParamCycle.d.ts +22 -0
- package/dist/lib/backends/valueParamCycle.js +41 -0
- package/dist/lib/cli/commands.js +6 -2
- package/dist/lib/cli/runBundledAgent.d.ts +10 -0
- package/dist/lib/cli/runBundledAgent.js +47 -18
- package/dist/lib/cli/runBundledAgent.test.js +37 -1
- package/dist/lib/cli/test.js +9 -0
- package/dist/lib/cli/util.js +14 -0
- package/dist/lib/compiler/buildManifest.d.ts +40 -0
- package/dist/lib/compiler/buildManifest.js +210 -0
- package/dist/lib/compiler/buildManifest.test.d.ts +1 -0
- package/dist/lib/compiler/buildManifest.test.js +179 -0
- package/dist/lib/compiler/buildSession.d.ts +29 -12
- package/dist/lib/compiler/buildSession.js +177 -32
- package/dist/lib/compiler/buildSession.test.js +206 -22
- package/dist/lib/compiler/compileClosure.d.ts +10 -0
- package/dist/lib/compiler/compileClosure.js +18 -1
- package/dist/lib/compiler/compileClosure.test.js +24 -2
- package/dist/lib/compiler/manifestTracker.d.ts +33 -0
- package/dist/lib/compiler/manifestTracker.js +112 -0
- package/dist/lib/compiler/manifestTracker.test.d.ts +1 -0
- package/dist/lib/compiler/manifestTracker.test.js +98 -0
- package/dist/lib/config.d.ts +11 -0
- package/dist/lib/config.js +1 -0
- package/dist/lib/logsViewer/summary.js +19 -0
- package/dist/lib/logsViewer/summary.test.js +61 -0
- package/dist/lib/logsViewer/tree.d.ts +10 -0
- package/dist/lib/logsViewer/tree.js +58 -4
- package/dist/lib/logsViewer/tree.test.js +107 -0
- package/dist/lib/optimize/constraint.test.js +9 -7
- package/dist/lib/runtime/agencyFunction.d.ts +12 -0
- package/dist/lib/runtime/agencyFunction.js +18 -0
- package/dist/lib/runtime/call.js +17 -0
- package/dist/lib/runtime/configOverrides.d.ts +2 -0
- package/dist/lib/runtime/configOverrides.js +5 -0
- package/dist/lib/runtime/configOverrides.test.js +24 -0
- package/dist/lib/runtime/failurePropagation.d.ts +65 -0
- package/dist/lib/runtime/failurePropagation.js +205 -0
- package/dist/lib/runtime/failurePropagation.test.d.ts +1 -0
- package/dist/lib/runtime/failurePropagation.test.js +381 -0
- package/dist/lib/runtime/index.d.ts +2 -1
- package/dist/lib/runtime/index.js +1 -0
- package/dist/lib/runtime/ipc.js +1 -6
- package/dist/lib/runtime/llmRetry.d.ts +10 -0
- package/dist/lib/runtime/llmRetry.js +25 -0
- package/dist/lib/runtime/llmRetry.test.js +22 -1
- package/dist/lib/runtime/prompt.d.ts +13 -0
- package/dist/lib/runtime/prompt.js +57 -6
- package/dist/lib/runtime/prompt.test.js +49 -0
- package/dist/lib/runtime/result.d.ts +14 -0
- package/dist/lib/runtime/result.js +13 -0
- package/dist/lib/runtime/result.test.js +2 -0
- package/dist/lib/runtime/runner.js +37 -30
- package/dist/lib/runtime/state/context.d.ts +2 -0
- package/dist/lib/runtime/state/context.js +7 -0
- package/dist/lib/runtime/threadEndHooksEvents.d.ts +28 -0
- package/dist/lib/runtime/threadEndHooksEvents.js +49 -0
- package/dist/lib/runtime/threadEndHooksEvents.test.d.ts +1 -0
- package/dist/lib/runtime/threadEndHooksEvents.test.js +71 -0
- package/dist/lib/runtime/truncate.d.ts +6 -0
- package/dist/lib/runtime/truncate.js +26 -0
- package/dist/lib/runtime/validateChain.d.ts +12 -0
- package/dist/lib/runtime/validateChain.js +23 -1
- package/dist/lib/runtime/validateChain.test.js +77 -0
- package/dist/lib/statelogClient.d.ts +61 -1
- package/dist/lib/statelogClient.js +73 -0
- package/dist/lib/statelogClient.test.js +66 -0
- package/dist/lib/stdlib/builtins.js +16 -0
- package/dist/lib/stdlib/http.d.ts +6 -6
- package/dist/lib/stdlib/http.js +52 -26
- package/dist/lib/stdlib/shell.js +41 -12
- package/dist/lib/stdlib/version.d.ts +1 -1
- package/dist/lib/stdlib/version.js +1 -1
- package/dist/lib/typeChecker/assignability.js +63 -68
- package/dist/lib/typeChecker/builtinGenerics.d.ts +53 -0
- package/dist/lib/typeChecker/builtinGenerics.js +226 -0
- package/dist/lib/typeChecker/builtinGenerics.test.d.ts +1 -0
- package/dist/lib/typeChecker/builtinGenerics.test.js +540 -0
- package/dist/lib/typeChecker/flow.d.ts +8 -10
- package/dist/lib/typeChecker/flow.js +14 -12
- package/dist/lib/typeChecker/handlerParamTyping.js +7 -0
- package/dist/lib/typeChecker/handlerParamTyping.test.js +7 -0
- package/dist/lib/typeChecker/index.js +33 -27
- package/dist/lib/typeChecker/matchExprTypes.js +8 -0
- package/dist/lib/typeChecker/matchExpression.test.js +7 -0
- package/dist/lib/typeChecker/nullLiteralSynth.test.d.ts +1 -0
- package/dist/lib/typeChecker/nullLiteralSynth.test.js +36 -0
- package/dist/lib/typeChecker/paramAcceptsFailure.test.d.ts +1 -0
- package/dist/lib/typeChecker/paramAcceptsFailure.test.js +35 -0
- package/dist/lib/typeChecker/recursiveAssignability.test.d.ts +1 -0
- package/dist/lib/typeChecker/recursiveAssignability.test.js +94 -0
- package/dist/lib/typeChecker/resultUnion.js +16 -0
- package/dist/lib/typeChecker/strictMemberAccess.test.js +34 -0
- package/dist/lib/typeChecker/synthesizer.js +28 -6
- package/dist/lib/typeChecker/typeKey.d.ts +24 -0
- package/dist/lib/typeChecker/typeKey.js +83 -0
- package/dist/lib/typeChecker/typeKey.test.d.ts +1 -0
- package/dist/lib/typeChecker/typeKey.test.js +165 -0
- package/dist/lib/typeChecker/utils.d.ts +16 -0
- package/dist/lib/typeChecker/utils.js +40 -0
- package/dist/lib/typeChecker/validate.js +3 -6
- package/dist/scripts/agency.js +5 -1
- package/dist/scripts/stage-agents.test.d.ts +1 -0
- package/dist/scripts/stage-agents.test.js +50 -0
- package/dist/scripts/stdlib-stamp.d.ts +1 -0
- package/dist/scripts/stdlib-stamp.js +31 -0
- package/package.json +1 -1
- package/stdlib/agency/eval.js +64 -32
- package/stdlib/agency/local.js +24 -12
- package/stdlib/agency.js +84 -42
- package/stdlib/agent.js +44 -22
- package/stdlib/args.js +2 -1
- package/stdlib/array.js +54 -27
- package/stdlib/auth/keyring.js +14 -7
- package/stdlib/auth/oauth.js +22 -11
- package/stdlib/calendar.js +44 -22
- package/stdlib/capabilities.agency +1 -1
- package/stdlib/capabilities.js +1 -1
- package/stdlib/clipboard.js +2 -1
- package/stdlib/concurrency.js +8 -4
- package/stdlib/data/finance/dbnomics.js +16 -8
- package/stdlib/data/finance/edgar.js +40 -20
- package/stdlib/data/finance/fred.js +52 -26
- package/stdlib/data/finance/gdelt.js +16 -8
- package/stdlib/data/people/littlesis.js +52 -26
- package/stdlib/data/tech/hackernews.js +72 -36
- package/stdlib/data/tech/yc.js +32 -16
- package/stdlib/data/usaspending.agency +263 -0
- package/stdlib/data/usaspending.js +2304 -0
- package/stdlib/data/wikidata.js +46 -23
- package/stdlib/date.js +56 -28
- package/stdlib/fs.js +40 -20
- package/stdlib/git.js +96 -48
- package/stdlib/http.agency +31 -15
- package/stdlib/http.js +138 -37
- package/stdlib/image.js +16 -8
- package/stdlib/index.agency +1 -1
- package/stdlib/index.js +113 -57
- package/stdlib/llm.js +18 -9
- package/stdlib/markdown.js +10 -5
- package/stdlib/math.js +20 -10
- package/stdlib/memory.agency +1 -1
- package/stdlib/memory.js +15 -8
- package/stdlib/messaging/email.js +70 -35
- package/stdlib/messaging/imessage.js +8 -4
- package/stdlib/messaging/sms.js +14 -7
- package/stdlib/object.js +26 -13
- package/stdlib/path.js +18 -9
- package/stdlib/policy.js +56 -28
- package/stdlib/shell.js +84 -42
- package/stdlib/skills.js +26 -13
- package/stdlib/speech.js +22 -11
- package/stdlib/statelog.js +22 -11
- package/stdlib/strategy.js +28 -14
- package/stdlib/syntax.js +46 -23
- package/stdlib/system.js +28 -14
- package/stdlib/tag.js +20 -10
- package/stdlib/thread.js +44 -22
- package/stdlib/ui/chart.js +36 -18
- package/stdlib/ui/cli.js +18 -9
- package/stdlib/ui/layout.js +186 -93
- package/stdlib/ui/table.js +54 -27
- package/stdlib/ui.js +414 -207
- package/stdlib/validation.js +32 -16
- package/stdlib/weather.js +8 -4
- package/stdlib/web/browser.js +14 -7
- package/stdlib/web/search.js +24 -12
- package/stdlib/wikipedia.js +8 -4
|
@@ -57,7 +57,8 @@ import {
|
|
|
57
57
|
BUILTIN_POLICIES,
|
|
58
58
|
} from "./lib/defaultPolicy.agency"
|
|
59
59
|
import { filterHostedModels, ModelFilters } from "./lib/modelFilters.agency"
|
|
60
|
-
import { parseModelFlag, knownProviders, Resolved } from "./lib/models.agency"
|
|
60
|
+
import { parseModelFlag, parseModelSpec, knownProviders, embeddingSpecHasProvider, missingProviderEnvVar, Resolved } from "./lib/models.agency"
|
|
61
|
+
import { SLOTS } from "./lib/slots.agency"
|
|
61
62
|
import {
|
|
62
63
|
buildLayers,
|
|
63
64
|
resolveAll,
|
|
@@ -71,7 +72,19 @@ import {
|
|
|
71
72
|
getSearchBackend,
|
|
72
73
|
availableBackendItems,
|
|
73
74
|
} from "./lib/search.agency"
|
|
74
|
-
import {
|
|
75
|
+
import {
|
|
76
|
+
CAPABILITY_FIELDS,
|
|
77
|
+
CapabilityPatch,
|
|
78
|
+
mergeCapabilityOverride,
|
|
79
|
+
removeCapabilityField,
|
|
80
|
+
providerLacksEmbeddings,
|
|
81
|
+
} from "./lib/capabilities.agency"
|
|
82
|
+
import {
|
|
83
|
+
getCapabilitySettings,
|
|
84
|
+
getModelSettings,
|
|
85
|
+
loadSettings,
|
|
86
|
+
saveSettings,
|
|
87
|
+
} from "./lib/settings.agency"
|
|
75
88
|
import { truncate, formatArgs, formatToolResponse } from "./lib/utils.agency"
|
|
76
89
|
import {
|
|
77
90
|
configureModels,
|
|
@@ -82,6 +95,17 @@ import {
|
|
|
82
95
|
promoteAll,
|
|
83
96
|
currentProvider,
|
|
84
97
|
resolveMaxToolCallRounds,
|
|
98
|
+
getCapabilities,
|
|
99
|
+
getCapabilitiesResolved,
|
|
100
|
+
getCapabilityModelKey,
|
|
101
|
+
getCapabilityProvider,
|
|
102
|
+
refreshCapabilities,
|
|
103
|
+
embeddingKeyStatus,
|
|
104
|
+
memoryEnablePlan,
|
|
105
|
+
overrideFromResolved,
|
|
106
|
+
embeddingsOverride,
|
|
107
|
+
providerEnvMissing,
|
|
108
|
+
demoteProvider,
|
|
85
109
|
} from "./shared.agency"
|
|
86
110
|
import { codeAgent, setCodeOneShot } from "./subagents/code.agency"
|
|
87
111
|
import { explorerAgent } from "./subagents/explorer.agency"
|
|
@@ -314,6 +338,7 @@ def builtinPalette(): Record<string, string> {
|
|
|
314
338
|
"/models": "List / filter the hosted model catalog",
|
|
315
339
|
"/local": "Switch to a local model",
|
|
316
340
|
"/search": "Choose the web search backend (hosted / Tavily / Brave / off)",
|
|
341
|
+
"/settings": "View and change capability settings for the current model",
|
|
317
342
|
"/paste": "Multi-line paste mode (Ctrl+D submits, Ctrl+C cancels)",
|
|
318
343
|
"/help": "Show available slash commands"
|
|
319
344
|
}
|
|
@@ -361,6 +386,15 @@ export def switchModel(
|
|
|
361
386
|
ctx: Ctx,
|
|
362
387
|
before: Record<string, Resolved>,
|
|
363
388
|
): { session: Session; resolved: Record<string, Resolved>; changes: SlotChange[] } {
|
|
389
|
+
// The caller builds ctx from currentProvider(), which returns the
|
|
390
|
+
// PROMOTED name on openai sessions. priceDefault and the built-in
|
|
391
|
+
// tables key by public provider names, so demote before resolving —
|
|
392
|
+
// otherwise a switch that lets any slot fall through to the built-in
|
|
393
|
+
// defaults fails with "openai-responses has no built-in defaults".
|
|
394
|
+
const ctx2: Ctx = {
|
|
395
|
+
provider: demoteProvider(ctx.provider),
|
|
396
|
+
price: ctx.price
|
|
397
|
+
}
|
|
364
398
|
let nextSlots: Record<string, string> = {}
|
|
365
399
|
for (key in Object.keys(prior.slots)) {
|
|
366
400
|
nextSlots[key] = prior.slots[key]
|
|
@@ -370,9 +404,23 @@ export def switchModel(
|
|
|
370
404
|
slots: nextSlots
|
|
371
405
|
}
|
|
372
406
|
const parsed = parseModelFlag(spec)
|
|
373
|
-
if (parsed.slot != "" &&
|
|
407
|
+
if (parsed.slot != "" && !SLOTS.includes(parsed.slot)) {
|
|
408
|
+
pushMessage(
|
|
409
|
+
color.red("Unknown model slot '${parsed.slot}'. Valid slots: ${SLOTS.join(", ")}."),
|
|
410
|
+
)
|
|
411
|
+
return {
|
|
412
|
+
session: prior,
|
|
413
|
+
resolved: before,
|
|
414
|
+
changes: []
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
if (parsed.slot == "embedding" && !embeddingSpecHasProvider(parsed.model)) {
|
|
418
|
+
// The embedding slot exists to point AWAY from the chat provider, so
|
|
419
|
+
// the provider can never be inferred. Require the explicit form.
|
|
374
420
|
pushMessage(
|
|
375
|
-
color.red(
|
|
421
|
+
color.red(
|
|
422
|
+
"Embedding models need the provider/model form, e.g. embedding=openai/text-embedding-3-small.",
|
|
423
|
+
),
|
|
376
424
|
)
|
|
377
425
|
return {
|
|
378
426
|
session: prior,
|
|
@@ -399,7 +447,7 @@ export def switchModel(
|
|
|
399
447
|
knownProviders(),
|
|
400
448
|
providerEstablished,
|
|
401
449
|
)
|
|
402
|
-
const all = resolveAll(layers,
|
|
450
|
+
const all = resolveAll(layers, ctx2)
|
|
403
451
|
if (isFailure(all)) {
|
|
404
452
|
pushMessage(color.red("Could not switch model: ${all.error}"))
|
|
405
453
|
return {
|
|
@@ -423,6 +471,13 @@ export def switchModel(
|
|
|
423
471
|
returns when a selective toggle lands.) Returns true if it emitted the notice. */
|
|
424
472
|
export def reactToSlotChange(change: SlotChange): boolean {
|
|
425
473
|
if (change.slot == "main" && change.before.provider != change.after.provider) {
|
|
474
|
+
// Skip the pause only when startup actually enabled memory WITH the
|
|
475
|
+
// override. A set-but-keyless slot took the fallback path, so memory
|
|
476
|
+
// runs on derived embeddings and the provider change still shifts
|
|
477
|
+
// the embedding space behind recall.
|
|
478
|
+
if (_memoryEmbeddingsPinned) {
|
|
479
|
+
return false
|
|
480
|
+
}
|
|
426
481
|
pushMessage(
|
|
427
482
|
color.dim(
|
|
428
483
|
"Warning: provider changed - memory is paused until restart (recall would be unreliable).",
|
|
@@ -433,6 +488,28 @@ export def reactToSlotChange(change: SlotChange): boolean {
|
|
|
433
488
|
disableMemory() with approve
|
|
434
489
|
return true
|
|
435
490
|
}
|
|
491
|
+
if (change.slot == "embedding") {
|
|
492
|
+
const override = overrideFromResolved(change.after)
|
|
493
|
+
if (override != null) {
|
|
494
|
+
const missing = missingProviderEnvVar(override.provider)
|
|
495
|
+
if (missing != "") {
|
|
496
|
+
pushMessage(
|
|
497
|
+
color.yellow(
|
|
498
|
+
"Warning: the embedding slot needs ${missing}, which is not set. The assignment takes effect at next agent start, and memory falls back to the default embedding behavior until it is exported.",
|
|
499
|
+
),
|
|
500
|
+
)
|
|
501
|
+
return true
|
|
502
|
+
}
|
|
503
|
+
// The healthy path must not be silent: enableMemory already ran,
|
|
504
|
+
// so the user would otherwise believe embeddings switched now.
|
|
505
|
+
pushMessage(
|
|
506
|
+
color.dim(
|
|
507
|
+
"Embedding slot set: memory embeddings use ${override.provider}/${override.model} at next agent start.",
|
|
508
|
+
),
|
|
509
|
+
)
|
|
510
|
+
return true
|
|
511
|
+
}
|
|
512
|
+
}
|
|
436
513
|
return false
|
|
437
514
|
}
|
|
438
515
|
|
|
@@ -467,6 +544,290 @@ export def parseModelsFilters(cmd: string): ModelFilters {
|
|
|
467
544
|
}
|
|
468
545
|
}
|
|
469
546
|
|
|
547
|
+
/** Human label for a capability source layer. Interprets the source
|
|
548
|
+
strings resolveCapabilities emits (capabilities.agency). */
|
|
549
|
+
def capabilitySourceLabel(source: string): string {
|
|
550
|
+
if (source == "default") {
|
|
551
|
+
return "built-in default"
|
|
552
|
+
}
|
|
553
|
+
if (source == "provider") {
|
|
554
|
+
return "provider default: ${getCapabilityProvider()}"
|
|
555
|
+
}
|
|
556
|
+
if (source == "model") {
|
|
557
|
+
return "built-in for ${getCapabilityModelKey()}"
|
|
558
|
+
}
|
|
559
|
+
if (source == "user-global") {
|
|
560
|
+
return "your global override"
|
|
561
|
+
}
|
|
562
|
+
if (source == "user-provider") {
|
|
563
|
+
return "your override for ${getCapabilityProvider()}"
|
|
564
|
+
}
|
|
565
|
+
return "your override for ${getCapabilityModelKey()}"
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/** One "value (source)" cell. The typed Capabilities shape cannot be
|
|
569
|
+
indexed by a dynamic key, so this is the renderer's per-field switch. */
|
|
570
|
+
def capabilityRow(fieldKey: string): string {
|
|
571
|
+
const resolved = getCapabilitiesResolved()
|
|
572
|
+
const values = resolved.values
|
|
573
|
+
const sources = resolved.sources
|
|
574
|
+
if (fieldKey == "prompt") {
|
|
575
|
+
return "${values.prompt} (${capabilitySourceLabel(sources.prompt)})"
|
|
576
|
+
}
|
|
577
|
+
if (fieldKey == "summarize") {
|
|
578
|
+
return "${values.summarize} (${capabilitySourceLabel(sources.summarize)})"
|
|
579
|
+
}
|
|
580
|
+
if (fieldKey == "memory") {
|
|
581
|
+
return "${values.memory} (${capabilitySourceLabel(sources.memory)})"
|
|
582
|
+
}
|
|
583
|
+
let cap = "none"
|
|
584
|
+
if (values.maxTokens != null) {
|
|
585
|
+
cap = "${values.maxTokens}"
|
|
586
|
+
}
|
|
587
|
+
return "${cap} (${capabilitySourceLabel(sources.maxTokens)})"
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/** Render the current profile with per-field provenance. */
|
|
591
|
+
def showCapabilities() {
|
|
592
|
+
pushMessage("Capabilities for ${getCapabilityModelKey()} (${getCapabilityProvider()}):")
|
|
593
|
+
for (field in CAPABILITY_FIELDS) {
|
|
594
|
+
pushMessage(" ${field.label} ${capabilityRow(field.key)}")
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/** The settings.json key a scope writes under. Global's key is unused. */
|
|
599
|
+
def scopeTargetName(scopeKey: string): string {
|
|
600
|
+
if (scopeKey == "provider") {
|
|
601
|
+
return getCapabilityProvider()
|
|
602
|
+
}
|
|
603
|
+
return getCapabilityModelKey()
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/** Persist one override patch at a scope, then re-resolve. */
|
|
607
|
+
def saveCapabilityOverride(scopeKey: string, patch: CapabilityPatch) {
|
|
608
|
+
let settings = loadSettings()
|
|
609
|
+
settings.capabilities = mergeCapabilityOverride(
|
|
610
|
+
getCapabilitySettings(settings),
|
|
611
|
+
scopeKey,
|
|
612
|
+
scopeTargetName(scopeKey),
|
|
613
|
+
patch,
|
|
614
|
+
)
|
|
615
|
+
saveSettings(settings)
|
|
616
|
+
refreshCapabilities(getCapabilityModelKey(), getCapabilityProvider())
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/** Remove one field override at a scope, then re-resolve. */
|
|
620
|
+
def removeCapabilityOverride(scopeKey: string, fieldKey: string) {
|
|
621
|
+
let settings = loadSettings()
|
|
622
|
+
settings.capabilities = removeCapabilityField(
|
|
623
|
+
getCapabilitySettings(settings),
|
|
624
|
+
scopeKey,
|
|
625
|
+
scopeTargetName(scopeKey),
|
|
626
|
+
fieldKey,
|
|
627
|
+
)
|
|
628
|
+
saveSettings(settings)
|
|
629
|
+
refreshCapabilities(getCapabilityModelKey(), getCapabilityProvider())
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/** Ask which scope an override applies to. Returns "" on cancel. */
|
|
633
|
+
def pickOverrideScope(): string {
|
|
634
|
+
let scopeItems: ChoiceItem[] = []
|
|
635
|
+
scopeItems.push({
|
|
636
|
+
key: "model",
|
|
637
|
+
label: "this model (${getCapabilityModelKey()})"
|
|
638
|
+
})
|
|
639
|
+
scopeItems.push({
|
|
640
|
+
key: "provider",
|
|
641
|
+
label: "this provider (${getCapabilityProvider()})"
|
|
642
|
+
})
|
|
643
|
+
scopeItems.push({
|
|
644
|
+
key: "global",
|
|
645
|
+
label: "all models"
|
|
646
|
+
})
|
|
647
|
+
const scopeKey = chooseOption("Scope", "Where should this apply?", scopeItems, allowCancel: true)
|
|
648
|
+
if (scopeKey == null) {
|
|
649
|
+
return ""
|
|
650
|
+
}
|
|
651
|
+
return scopeKey
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/** Re-apply the resolved cap as the branch default. After a reset the
|
|
655
|
+
resolved value falls back to a built-in layer, which is always numeric
|
|
656
|
+
for known providers, so live-apply covers removal too. */
|
|
657
|
+
def applyLiveMaxTokens() {
|
|
658
|
+
const capValue = getCapabilities().maxTokens
|
|
659
|
+
if (capValue != null) {
|
|
660
|
+
setLlmOptions({ maxTokens: capValue })
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/** Positive-integer parse. parseInt and isNaN appear nowhere in the
|
|
665
|
+
repo's .agency code, so this uses a digits check instead. Returns -1
|
|
666
|
+
for anything that is not all digits. */
|
|
667
|
+
def parsePositiveInt(text: string): number {
|
|
668
|
+
// Bound to a const because the parser rejects method calls on string
|
|
669
|
+
// LITERALS ("0123456789".includes(...) does not parse; a variable does).
|
|
670
|
+
const digits = "0123456789"
|
|
671
|
+
const trimmed = text.trim()
|
|
672
|
+
if (trimmed == "") {
|
|
673
|
+
return -1
|
|
674
|
+
}
|
|
675
|
+
for (ch in trimmed.split("")) {
|
|
676
|
+
if (!digits.includes(ch)) {
|
|
677
|
+
return -1
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
return Number(trimmed)
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
/** Interactive edit: field → value → scope → save → live-apply. */
|
|
684
|
+
def editCapabilities() {
|
|
685
|
+
let fieldItems: ChoiceItem[] = []
|
|
686
|
+
for (field in CAPABILITY_FIELDS) {
|
|
687
|
+
fieldItems.push({
|
|
688
|
+
key: field.key,
|
|
689
|
+
label: "${field.label} — ${field.description}"
|
|
690
|
+
})
|
|
691
|
+
}
|
|
692
|
+
const fieldKey = chooseOption(
|
|
693
|
+
"Settings",
|
|
694
|
+
"Pick a setting to change (empty to exit).",
|
|
695
|
+
fieldItems,
|
|
696
|
+
allowCancel: true,
|
|
697
|
+
)
|
|
698
|
+
if (fieldKey == "" || fieldKey == null) {
|
|
699
|
+
return
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
let patch: CapabilityPatch = {}
|
|
703
|
+
if (fieldKey == "prompt") {
|
|
704
|
+
let promptItems: ChoiceItem[] = []
|
|
705
|
+
promptItems.push({
|
|
706
|
+
key: "large",
|
|
707
|
+
label: "large — full coordinator prompt"
|
|
708
|
+
})
|
|
709
|
+
promptItems.push({
|
|
710
|
+
key: "small",
|
|
711
|
+
label: "small — compact prompt for small-context models"
|
|
712
|
+
})
|
|
713
|
+
const picked = chooseOption("prompt", "System prompt size.", promptItems, allowCancel: true)
|
|
714
|
+
if (picked == "" || picked == null) {
|
|
715
|
+
return
|
|
716
|
+
}
|
|
717
|
+
patch = {
|
|
718
|
+
prompt: picked
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
if (fieldKey == "summarize" || fieldKey == "memory") {
|
|
722
|
+
let onOffItems: ChoiceItem[] = []
|
|
723
|
+
onOffItems.push({
|
|
724
|
+
key: "on",
|
|
725
|
+
label: "on"
|
|
726
|
+
})
|
|
727
|
+
onOffItems.push({
|
|
728
|
+
key: "off",
|
|
729
|
+
label: "off"
|
|
730
|
+
})
|
|
731
|
+
const picked = chooseOption(fieldKey, "Enable ${fieldKey}?", onOffItems, allowCancel: true)
|
|
732
|
+
if (picked == "" || picked == null) {
|
|
733
|
+
return
|
|
734
|
+
}
|
|
735
|
+
if (fieldKey == "summarize") {
|
|
736
|
+
patch = {
|
|
737
|
+
summarize: picked == "on"
|
|
738
|
+
}
|
|
739
|
+
} else {
|
|
740
|
+
patch = {
|
|
741
|
+
memory: picked == "on"
|
|
742
|
+
}
|
|
743
|
+
if (picked == "on") {
|
|
744
|
+
const status = embeddingKeyStatus(getResolvedSlots())
|
|
745
|
+
if (status.state == "key-missing") {
|
|
746
|
+
pushMessage(
|
|
747
|
+
color.red(
|
|
748
|
+
"Cannot enable memory: the embedding slot needs ${status.varName}, which is not set. Export it, or point the embedding slot elsewhere via /model.",
|
|
749
|
+
),
|
|
750
|
+
)
|
|
751
|
+
return
|
|
752
|
+
}
|
|
753
|
+
if (status.state == "no-override" && providerLacksEmbeddings(getCapabilityProvider())) {
|
|
754
|
+
pushMessage(
|
|
755
|
+
color.dim(
|
|
756
|
+
"Note: ${getCapabilityProvider()} has no embeddings endpoint, so Tier-2 semantic recall stays off. Point the embedding slot at a provider that has one, e.g. /model embedding=openai/text-embedding-3-small.",
|
|
757
|
+
),
|
|
758
|
+
)
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
if (fieldKey == "maxTokens") {
|
|
764
|
+
let capItems: ChoiceItem[] = []
|
|
765
|
+
capItems.push({
|
|
766
|
+
key: "reset",
|
|
767
|
+
label: "reset — remove my override, use the default"
|
|
768
|
+
})
|
|
769
|
+
const picked = chooseOption(
|
|
770
|
+
"maxTokens",
|
|
771
|
+
"Default output-token cap. Type a number, or pick reset.",
|
|
772
|
+
capItems,
|
|
773
|
+
allowFreeText: true,
|
|
774
|
+
allowCancel: true,
|
|
775
|
+
)
|
|
776
|
+
if (picked == "" || picked == null) {
|
|
777
|
+
return
|
|
778
|
+
}
|
|
779
|
+
if (picked == "reset") {
|
|
780
|
+
const scopeKey = pickOverrideScope()
|
|
781
|
+
if (scopeKey == "") {
|
|
782
|
+
return
|
|
783
|
+
}
|
|
784
|
+
removeCapabilityOverride(scopeKey, "maxTokens")
|
|
785
|
+
applyLiveMaxTokens()
|
|
786
|
+
pushMessage("Override removed.")
|
|
787
|
+
showCapabilities()
|
|
788
|
+
return
|
|
789
|
+
}
|
|
790
|
+
const parsed = parsePositiveInt(picked)
|
|
791
|
+
if (parsed <= 0) {
|
|
792
|
+
pushMessage(color.red("Not a positive number: ${picked}"))
|
|
793
|
+
return
|
|
794
|
+
}
|
|
795
|
+
patch = {
|
|
796
|
+
maxTokens: parsed
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
const scopeKey = pickOverrideScope()
|
|
801
|
+
if (scopeKey == "") {
|
|
802
|
+
return
|
|
803
|
+
}
|
|
804
|
+
saveCapabilityOverride(scopeKey, patch)
|
|
805
|
+
|
|
806
|
+
// Live-apply what can apply now; explain what can't.
|
|
807
|
+
if (fieldKey == "memory") {
|
|
808
|
+
if (getCapabilities().memory) {
|
|
809
|
+
// The ON direction cannot live-apply. enableAgentMemory's
|
|
810
|
+
// `with approve` cannot override the outer policy handler that
|
|
811
|
+
// startInteractive installed, so the memory-dir fs interrupts
|
|
812
|
+
// would surface as policy prompts mid-flow, or get denied and
|
|
813
|
+
// half-apply the toggle. The OFF direction stays live below:
|
|
814
|
+
// disableMemory raises no fs interrupts and already runs in-REPL
|
|
815
|
+
// from reactToSlotChange.
|
|
816
|
+
pushMessage(color.dim("Memory turns on at next agent start (enabling mid-session would raise policy prompts)."))
|
|
817
|
+
} else {
|
|
818
|
+
disableMemory() with approve
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
if (fieldKey == "maxTokens") {
|
|
822
|
+
applyLiveMaxTokens()
|
|
823
|
+
}
|
|
824
|
+
if (fieldKey == "prompt") {
|
|
825
|
+
pushMessage(color.dim("Prompt change applies on next agent start (this session's system message is already sent)."))
|
|
826
|
+
}
|
|
827
|
+
pushMessage("Saved.")
|
|
828
|
+
showCapabilities()
|
|
829
|
+
}
|
|
830
|
+
|
|
470
831
|
// Slash-command + user-message dispatcher invoked by `repl()` for
|
|
471
832
|
// every Enter keystroke. Return `false` to terminate the loop.
|
|
472
833
|
def _runTurn(msg: string): boolean {
|
|
@@ -493,10 +854,15 @@ def _runTurn(msg: string): boolean {
|
|
|
493
854
|
}
|
|
494
855
|
if (trimmed == "/help") {
|
|
495
856
|
pushMessage(
|
|
496
|
-
"Commands: /exit, /clear, /clear-history, /cost, /model, /models, /local, /search, /paste, /help",
|
|
857
|
+
"Commands: /exit, /clear, /clear-history, /cost, /model, /models, /local, /search, /settings, /paste, /help",
|
|
497
858
|
)
|
|
498
859
|
return true
|
|
499
860
|
}
|
|
861
|
+
if (trimmed == "/settings") {
|
|
862
|
+
showCapabilities()
|
|
863
|
+
editCapabilities()
|
|
864
|
+
return true
|
|
865
|
+
}
|
|
500
866
|
if (trimmed == "/search") {
|
|
501
867
|
const opts = availableBackendItems()
|
|
502
868
|
const choice = chooseOption(
|
|
@@ -661,7 +1027,7 @@ let first = true
|
|
|
661
1027
|
// subagent. Used to validate the flag and to dispatch in `agentReplyVia`.
|
|
662
1028
|
static const START_AGENTS = ["main", "code", "research", "oracle", "explorer", "review"]
|
|
663
1029
|
|
|
664
|
-
static const
|
|
1030
|
+
static const MAIN_PROMPT_LARGE = """
|
|
665
1031
|
You are the top-level coordinator of an Agency-language assistant. You
|
|
666
1032
|
receive every user message and decide how to respond.
|
|
667
1033
|
|
|
@@ -830,6 +1196,41 @@ unless the user has clearly asked for an action ("do X", "fix Y",
|
|
|
830
1196
|
with them — don't sprint to implementation.
|
|
831
1197
|
"""
|
|
832
1198
|
|
|
1199
|
+
// Compact coordinator prompt for small-context models, ~350 tokens
|
|
1200
|
+
// instead of ~3,400. Selected when the capability profile says
|
|
1201
|
+
// prompt: "small". An 8K-context model loses 40% of its window to the
|
|
1202
|
+
// large prompt before the user types anything. The phrase "compact
|
|
1203
|
+
// coordinator" is a deliberate marker that verification greps for in
|
|
1204
|
+
// statelogs.
|
|
1205
|
+
static const MAIN_PROMPT_SMALL = """
|
|
1206
|
+
You are the compact coordinator of an Agency-language assistant. Decide
|
|
1207
|
+
how to answer each user message.
|
|
1208
|
+
|
|
1209
|
+
Tools (each runs in its own context; pass a self-contained message):
|
|
1210
|
+
- `codeAgent(userMsg)` — anything touching code or files: read, write,
|
|
1211
|
+
edit, run, typecheck. Also Agency syntax and CLI questions.
|
|
1212
|
+
- `researchAgent(userMsg)` — web search, URL fetches, external facts.
|
|
1213
|
+
- `reviewAgent(userMsg)` — check non-trivial new Agency code for
|
|
1214
|
+
syntax and type errors; pass the code to review.
|
|
1215
|
+
- `oracleAgent(userMsg)` — deep reasoning on a hard question; include
|
|
1216
|
+
all needed context in the message.
|
|
1217
|
+
- `explorerAgent(userMsg)` — broad read-only codebase/docs questions.
|
|
1218
|
+
- `generateImageFile(prompt, path, size, images)` — create or edit an
|
|
1219
|
+
image; do not route image work to codeAgent.
|
|
1220
|
+
|
|
1221
|
+
Routing rules:
|
|
1222
|
+
- Simple chat, greetings, quick factual answers: reply directly, no
|
|
1223
|
+
tools.
|
|
1224
|
+
- Anything code- or file-related: codeAgent. Current/external info:
|
|
1225
|
+
researchAgent. Broad "summarize/tour/how does X work" questions:
|
|
1226
|
+
explorerAgent.
|
|
1227
|
+
- Surface tool results to the user concisely; do not re-run a tool the
|
|
1228
|
+
user did not ask to re-run.
|
|
1229
|
+
|
|
1230
|
+
Style: plain, direct answers in Markdown. No preamble. Keep replies
|
|
1231
|
+
short unless the task demands detail.
|
|
1232
|
+
"""
|
|
1233
|
+
|
|
833
1234
|
// Exported for tests: agent-cwd resolution of edit inputs is a spec
|
|
834
1235
|
// invariant with no other observable (the deterministic image client
|
|
835
1236
|
// ignores its images argument). generateImage accepts path / URL /
|
|
@@ -902,14 +1303,56 @@ static const mainAgentTools = [
|
|
|
902
1303
|
generateImageFile,
|
|
903
1304
|
]
|
|
904
1305
|
|
|
1306
|
+
/** Enable memory when the capability profile allows it. When the user
|
|
1307
|
+
pointed the embedding slot at a provider, embeddings run there. A
|
|
1308
|
+
missing API key degrades to the default embedding behavior with one
|
|
1309
|
+
notice. It never blocks startup. */
|
|
1310
|
+
// Whether startup actually enabled memory WITH the embedding override.
|
|
1311
|
+
// The pause guard in reactToSlotChange consults this instead of
|
|
1312
|
+
// re-deriving from the slots: a keyless override took the fallback path,
|
|
1313
|
+
// so memory runs on DERIVED embeddings and a main-provider change still
|
|
1314
|
+
// shifts the embedding space. Exported mutator so tests can drive the
|
|
1315
|
+
// guard directly.
|
|
1316
|
+
let _memoryEmbeddingsPinned = false
|
|
1317
|
+
|
|
1318
|
+
export def markMemoryEmbeddingsPinned(pinned: boolean) {
|
|
1319
|
+
_memoryEmbeddingsPinned = pinned
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
def maybeEnableMemory() {
|
|
1323
|
+
const status = embeddingKeyStatus(getResolvedSlots())
|
|
1324
|
+
const plan = memoryEnablePlan(getCapabilities().memory, status)
|
|
1325
|
+
markMemoryEmbeddingsPinned(plan == "enable-override")
|
|
1326
|
+
if (plan == "skip") {
|
|
1327
|
+
return
|
|
1328
|
+
}
|
|
1329
|
+
if (plan == "enable-override") {
|
|
1330
|
+
enableAgentMemory(status.override)
|
|
1331
|
+
return
|
|
1332
|
+
}
|
|
1333
|
+
if (plan == "enable-fallback") {
|
|
1334
|
+
print(
|
|
1335
|
+
color.dim(
|
|
1336
|
+
"Memory: the embedding slot needs ${status.varName}, which is not set. Falling back to the default embedding behavior.",
|
|
1337
|
+
),
|
|
1338
|
+
)
|
|
1339
|
+
}
|
|
1340
|
+
enableAgentMemory()
|
|
1341
|
+
}
|
|
1342
|
+
|
|
905
1343
|
def mainAgent(prompt: string | (string | Attachment)[]): string {
|
|
906
|
-
|
|
1344
|
+
const doSummarize = getCapabilities().summarize
|
|
1345
|
+
thread(label: "main", summarize: doSummarize, session: "main") {
|
|
907
1346
|
setMemoryId("main")
|
|
908
1347
|
if (first) {
|
|
909
1348
|
// `_context` carries the per-run grounding (date, cwd, AGENTS.md),
|
|
910
1349
|
// set by `setupSession`. Appending it to the system prompt is what
|
|
911
1350
|
// actually gets that context to the LLM.
|
|
912
|
-
|
|
1351
|
+
let sysPrompt = MAIN_PROMPT_LARGE
|
|
1352
|
+
if (getCapabilities().prompt == "small") {
|
|
1353
|
+
sysPrompt = MAIN_PROMPT_SMALL
|
|
1354
|
+
}
|
|
1355
|
+
systemMessage("${sysPrompt}${_context}")
|
|
913
1356
|
first = false
|
|
914
1357
|
}
|
|
915
1358
|
const result = llm(prompt, {
|
|
@@ -1259,6 +1702,10 @@ node main() {
|
|
|
1259
1702
|
optional: true,
|
|
1260
1703
|
description: "Approval policy for this run: a built-in name (minimal, recommended, with-writes, approve-all) or a path to a policy JSON file. with-writes auto-approves file writes and git changes scoped to the current directory and its children; approve-all approves EVERY interrupt with no scoping (sandbox use only). Overrides the saved policy without persisting it. Pass --policy with no value to list the built-in policies."
|
|
1261
1704
|
},
|
|
1705
|
+
"agent-home": {
|
|
1706
|
+
type: "string",
|
|
1707
|
+
description: "Directory to use instead of ~/.agency-agent for settings, policy, and history (equivalent to the AGENCY_AGENT_HOME env var; the flag wins when both are set)"
|
|
1708
|
+
},
|
|
1262
1709
|
local: {
|
|
1263
1710
|
type: "string",
|
|
1264
1711
|
optional: true,
|
|
@@ -1290,11 +1737,14 @@ node main() {
|
|
|
1290
1737
|
},
|
|
1291
1738
|
)
|
|
1292
1739
|
|
|
1293
|
-
// NOTE: --trace / --log-file are declared here only for
|
|
1294
|
-
// parseArgs accepts them. runBundledAgent extracts them from
|
|
1295
|
-
// args and passes them to this process
|
|
1296
|
-
//
|
|
1297
|
-
//
|
|
1740
|
+
// NOTE: --trace / --log-file / --agent-home are declared here only for
|
|
1741
|
+
// --help and so parseArgs accepts them. runBundledAgent extracts them from
|
|
1742
|
+
// the forwarded args and passes them to this process via env vars
|
|
1743
|
+
// (AGENCY_CONFIG_OVERRIDES for the first two, AGENCY_AGENT_HOME for the
|
|
1744
|
+
// last), read before this main() runs — the RuntimeContext consumes the
|
|
1745
|
+
// config overrides at construction, and lib/config.agency derives the
|
|
1746
|
+
// settings/policy/history paths from the agent home in its static-const
|
|
1747
|
+
// initializers. Do not re-handle them here.
|
|
1298
1748
|
|
|
1299
1749
|
if (args.flags.debug) {
|
|
1300
1750
|
AGENT_DEBUG = true
|
|
@@ -1359,9 +1809,6 @@ node main() {
|
|
|
1359
1809
|
// fall through into the session on the chosen local model
|
|
1360
1810
|
} else if (localVal != null) {
|
|
1361
1811
|
configureLocalModel(localVal)
|
|
1362
|
-
// Intentionally do NOT enable memory for a local model: the llama-cpp
|
|
1363
|
-
// provider has no embedding endpoint, so memory would only emit a
|
|
1364
|
-
// "Tier-2 disabled" notice. std::memory calls no-op while it's off.
|
|
1365
1812
|
configureSearch(true)
|
|
1366
1813
|
} else {
|
|
1367
1814
|
// Hosted path. --model accepts `slot=model` (per-slot) or a bare model
|
|
@@ -1370,6 +1817,7 @@ node main() {
|
|
|
1370
1817
|
let modelGlobal = ""
|
|
1371
1818
|
let fastFlag = ""
|
|
1372
1819
|
let slowFlag = ""
|
|
1820
|
+
let embeddingFlag = ""
|
|
1373
1821
|
if (modelArg != "") {
|
|
1374
1822
|
if (parsed.slot == "") {
|
|
1375
1823
|
modelGlobal = parsed.model
|
|
@@ -1377,10 +1825,20 @@ node main() {
|
|
|
1377
1825
|
fastFlag = parsed.model
|
|
1378
1826
|
} else if (parsed.slot == "reasoning") {
|
|
1379
1827
|
slowFlag = parsed.model
|
|
1828
|
+
} else if (parsed.slot == "embedding") {
|
|
1829
|
+
if (!embeddingSpecHasProvider(parsed.model)) {
|
|
1830
|
+
print(
|
|
1831
|
+
color.red(
|
|
1832
|
+
"Embedding models need the provider/model form, e.g. --model embedding=openai/text-embedding-3-small.",
|
|
1833
|
+
),
|
|
1834
|
+
)
|
|
1835
|
+
process.exit(1)
|
|
1836
|
+
}
|
|
1837
|
+
embeddingFlag = parsed.model
|
|
1380
1838
|
} else {
|
|
1381
1839
|
print(
|
|
1382
1840
|
color.red(
|
|
1383
|
-
"Unknown model slot '${parsed.slot}' in --model. Valid slots:
|
|
1841
|
+
"Unknown model slot '${parsed.slot}' in --model. Valid slots: ${SLOTS.join(", ")}.",
|
|
1384
1842
|
),
|
|
1385
1843
|
)
|
|
1386
1844
|
process.exit(1)
|
|
@@ -1394,16 +1852,14 @@ node main() {
|
|
|
1394
1852
|
if (sm != "") {
|
|
1395
1853
|
slowFlag = sm
|
|
1396
1854
|
}
|
|
1397
|
-
configureModels(modelGlobal, fastFlag, slowFlag, args.flags.provider ?? "")
|
|
1398
|
-
// Persistent knowledge graph — enabled for hosted providers, skipped for
|
|
1399
|
-
// local models. (Some hosted providers, e.g. anthropic, still lack an
|
|
1400
|
-
// embedding endpoint and just disable Tier-2 recall with a one-time
|
|
1401
|
-
// notice; structured recall works regardless.) Must run before any
|
|
1402
|
-
// handler/REPL is installed.
|
|
1403
|
-
enableAgentMemory()
|
|
1855
|
+
configureModels(modelGlobal, fastFlag, slowFlag, embeddingFlag, args.flags.provider ?? "")
|
|
1404
1856
|
configureSearch(false)
|
|
1405
1857
|
}
|
|
1406
1858
|
|
|
1859
|
+
// Persistent knowledge graph, gated on the capability profile. Must run
|
|
1860
|
+
// before any handler/REPL is installed.
|
|
1861
|
+
maybeEnableMemory()
|
|
1862
|
+
|
|
1407
1863
|
// Positional args (everything after flags) are joined with spaces to
|
|
1408
1864
|
// form the starting prompt. `--` ends flag parsing if a positional
|
|
1409
1865
|
// would otherwise look like a flag.
|
|
@@ -1434,20 +1890,15 @@ node main() {
|
|
|
1434
1890
|
setLlmOptions({ maxToolResultChars: maxResultChars })
|
|
1435
1891
|
}
|
|
1436
1892
|
|
|
1437
|
-
//
|
|
1438
|
-
//
|
|
1439
|
-
//
|
|
1440
|
-
//
|
|
1441
|
-
//
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
// inherits it; per-call `llm(..., { maxTokens })` (e.g. the summarizer's
|
|
1447
|
-
// cap) still wins. Superseded by the declarative capabilities table in
|
|
1448
|
-
// docs/superpowers/specs/2026-07-09-model-capabilities-design.md (§2,
|
|
1449
|
-
// maxTokens applied via setLlmOptions at startup) — remove it then.
|
|
1450
|
-
setLlmOptions({ maxTokens: 20000 })
|
|
1893
|
+
// Per-model default output cap from the capability profile. The hosted
|
|
1894
|
+
// default of 20000 carries the adaptive-thinking empty-reply fix that
|
|
1895
|
+
// used to live here as a TEMPORARY block. Local profiles cap lower.
|
|
1896
|
+
// Branch-scoped, so every subagent inherits it. A per-call
|
|
1897
|
+
// llm(..., { maxTokens }) still wins, e.g. the summarizer's 256.
|
|
1898
|
+
const capsMaxTokens = getCapabilities().maxTokens
|
|
1899
|
+
if (capsMaxTokens != null) {
|
|
1900
|
+
setLlmOptions({ maxTokens: capsMaxTokens })
|
|
1901
|
+
}
|
|
1451
1902
|
|
|
1452
1903
|
// One-shot autonomy: tell the code subagent there is no human to answer
|
|
1453
1904
|
// questions and no next turn, so it must drive to a finished artifact.
|