akm-cli 0.10.261017-beta → 0.10.261019
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/CHANGELOG.md +51 -0
- package/dist/assets/opencode/akm-plugin.js +103 -1
- package/dist/core/config/convert-engine-references.js +23 -7
- package/dist/core/config/convert-engines.js +94 -28
- package/dist/core/config/convert-models-overlay.js +14 -2
- package/dist/integrations/agent/spawn.js +7 -2
- package/dist/integrations/harnesses/opencode/agent-builder.js +10 -1
- package/dist/integrations/harnesses/opencode/runtime/binary.js +6 -3
- package/dist/integrations/harnesses/opencode/runtime/index.js +18 -9
- package/dist/integrations/harnesses/opencode/session-log-v2.js +11 -1
- package/dist/scripts/akm-migrate-node.js +91 -33
- package/dist/scripts/akm-migrate.js +91 -33
- package/docs/architecture/architecture.md +9 -3
- package/docs/architecture/testing/testing-workflow.md +1 -1
- package/docs/migration/README.md +1 -1
- package/docs/migration/release-notes/{0.10.0.md → 0.10.261019.md} +35 -4
- package/docs/migration/release-notes/README.md +1 -1
- package/docs/migration/v0.9-to-v0.10.md +58 -7
- package/docs/reference/configuration.md +45 -13
- package/package.json +1 -1
|
@@ -141,7 +141,7 @@ export function listV2Sessions(db, sinceMs) {
|
|
|
141
141
|
}
|
|
142
142
|
/**
|
|
143
143
|
* The tokens one session's turns used: OpenCode records them on each assistant message and keeps their sums on the
|
|
144
|
-
* session row (equal, measured on 2.1.4). Undefined when the session is not in the file.
|
|
144
|
+
* session row (equal, measured on 2.1.4 and 2.2.0). Undefined when the session is not in the file.
|
|
145
145
|
*/
|
|
146
146
|
export function v2SessionTokens(db, sessionId) {
|
|
147
147
|
const row = db
|
|
@@ -149,6 +149,16 @@ export function v2SessionTokens(db, sessionId) {
|
|
|
149
149
|
.get(sessionId);
|
|
150
150
|
return row ? { input: row.tokens_input, output: row.tokens_output, reasoning: row.tokens_reasoning } : undefined;
|
|
151
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* The message a session's turn failed with, as OpenCode recorded it on the session's `idle` message (an error a plugin
|
|
154
|
+
* hook threw, a provider's refusal). Undefined when the session is not in the file or its turn did not fail.
|
|
155
|
+
*/
|
|
156
|
+
export function v2SessionFailure(db, sessionId) {
|
|
157
|
+
const row = db
|
|
158
|
+
.prepare("SELECT json_extract(data, '$.error.message') AS message FROM session_message WHERE session_id = ? AND type = 'idle' AND json_extract(data, '$.outcome') = 'failed' ORDER BY seq DESC LIMIT 1")
|
|
159
|
+
.get(sessionId);
|
|
160
|
+
return typeof row?.message === "string" && row.message.trim() !== "" ? row.message : undefined;
|
|
161
|
+
}
|
|
152
162
|
/** One session's events, from its messages in order. Throws when the session is not in the file. */
|
|
153
163
|
export function readV2Session(db, harness, sessionId, filePath) {
|
|
154
164
|
const row = db
|
|
@@ -30476,6 +30476,7 @@ function modelWorkConfig() {
|
|
|
30476
30476
|
}
|
|
30477
30477
|
const config2 = {
|
|
30478
30478
|
...user,
|
|
30479
|
+
plugins: [...Array.isArray(user?.plugins) ? user.plugins : [], WITHOUT_BROWSER_PLUGIN],
|
|
30479
30480
|
agents: { ...asRecord(user?.agents), [MODEL_WORK_AGENT]: MODEL_WORK_AGENT_DEFINITION }
|
|
30480
30481
|
};
|
|
30481
30482
|
const legacy = asRecord(user?.agent);
|
|
@@ -30508,7 +30509,7 @@ function withEnvReferences(content) {
|
|
|
30508
30509
|
return replaced(true);
|
|
30509
30510
|
}
|
|
30510
30511
|
}
|
|
30511
|
-
var MODEL_WORK_AGENT = "akm-model-work", MODEL_WORK_AGENT_DEFINITION, CONFIG_CONTENT_ENV = "OPENCODE_CONFIG_CONTENT", NO_FREE_MODELS, opencodeBuilder;
|
|
30512
|
+
var MODEL_WORK_AGENT = "akm-model-work", MODEL_WORK_AGENT_DEFINITION, CONFIG_CONTENT_ENV = "OPENCODE_CONFIG_CONTENT", WITHOUT_BROWSER_PLUGIN = "-opencode.browser", NO_FREE_MODELS, opencodeBuilder;
|
|
30512
30513
|
var init_agent_builder = __esm(() => {
|
|
30513
30514
|
init_common();
|
|
30514
30515
|
init_warn();
|
|
@@ -32114,13 +32115,22 @@ function improveStrategyDefault(out, defaults, improve) {
|
|
|
32114
32115
|
out.improve = { ...isRecord(improve) ? improve : {} };
|
|
32115
32116
|
out.improve.strategy ??= defaults.improveStrategy;
|
|
32116
32117
|
}
|
|
32117
|
-
function dropJudgeEngine(out, conversion) {
|
|
32118
|
+
function dropJudgeEngine(out, conversion, target, defaultEngine, judge) {
|
|
32118
32119
|
const workflow = out.workflow;
|
|
32119
|
-
|
|
32120
|
-
|
|
32121
|
-
|
|
32122
|
-
|
|
32123
|
-
|
|
32120
|
+
const named = isRecord(workflow) && "judgeEngine" in workflow;
|
|
32121
|
+
const engine = named ? str(workflow.judgeEngine) : defaultEngine;
|
|
32122
|
+
if (named) {
|
|
32123
|
+
delete workflow.judgeEngine;
|
|
32124
|
+
conversion.changed = true;
|
|
32125
|
+
}
|
|
32126
|
+
const became = engine === undefined ? undefined : target(engine);
|
|
32127
|
+
const stays = became !== undefined && judge !== undefined && isDeepStrictEqual(became, judge);
|
|
32128
|
+
const kind = judge === undefined ? undefined : ("connection" in judge) ? "connection" : "harness";
|
|
32129
|
+
if (named) {
|
|
32130
|
+
conversion.notes.push(stays ? `workflow.judgeEngine: "${engine}" is the default ${kind}, where a gate's judge runs now; the setting is dropped.` : `workflow.judgeEngine${engine === undefined ? "" : ` "${engine}"`}: dropped. A gate's judge runs on the default connection, else the default harness, so a judge that ran on another engine has moved; to keep it, make that engine the default.`);
|
|
32131
|
+
} else if (became !== undefined && judge !== undefined && !stays) {
|
|
32132
|
+
conversion.notes.push(`workflow: with no workflow.judgeEngine, a gate's judge ran on the default engine "${engine}"; it is model work now and runs on the default ${kind}, "${"connection" in judge ? judge.connection : judge.harness}".`);
|
|
32133
|
+
}
|
|
32124
32134
|
}
|
|
32125
32135
|
function convertIndexEngines(out, conversion, retarget) {
|
|
32126
32136
|
const index = out.index;
|
|
@@ -32187,6 +32197,8 @@ function foldModelsOverlay(modelsOverlay, fold) {
|
|
|
32187
32197
|
const writtenHarnesses = written.harnesses;
|
|
32188
32198
|
const configNames = (own2, base, name, alias) => hasModel(own2[name], alias) || hasModel(base[name], alias);
|
|
32189
32199
|
const platformOf = (name) => String((mergedHarnesses[name] ?? inheritedHarnesses[name])?.platform ?? name);
|
|
32200
|
+
const columnOf = (name) => renamed.sdkHarness.includes(name) ? "opencode-sdk" : platformOf(name);
|
|
32201
|
+
const notedOwn = new Set;
|
|
32190
32202
|
let folded = false;
|
|
32191
32203
|
for (const { alias, column, profile } of overlayRows(modelsOverlay)) {
|
|
32192
32204
|
const p = typeof profile === "string" ? { model: profile } : isRecord(profile) ? profile : {};
|
|
@@ -32198,13 +32210,18 @@ function foldModelsOverlay(modelsOverlay, fold) {
|
|
|
32198
32210
|
continue;
|
|
32199
32211
|
}
|
|
32200
32212
|
const candidates = column === "*" ? [...new Set([...Object.keys(mergedConnections), ...Object.keys(inheritedConnections)])] : column === "opencode-sdk" ? [...renamed.runtime] : renamed.connection(column) !== undefined ? [renamed.connection(column)] : (column in writtenConnections) || (column in inheritedConnections) ? [column] : [];
|
|
32201
|
-
const harnessNamed = [...new Set([...Object.keys(mergedHarnesses), ...Object.keys(inheritedHarnesses)])].filter((name) =>
|
|
32213
|
+
const harnessNamed = [...new Set([...Object.keys(mergedHarnesses), ...Object.keys(inheritedHarnesses)])].filter((name) => columnOf(name) === column);
|
|
32202
32214
|
if (candidates.length === 0 && harnessNamed.length === 0) {
|
|
32203
32215
|
notes2.push(`${where}: names no configured connection or harness, so it is not carried over.`);
|
|
32204
32216
|
continue;
|
|
32205
32217
|
}
|
|
32206
32218
|
const connectionNames = candidates.filter((name) => !configNames(writtenConnections, inheritedConnections, name, alias) && !(column === "*" && hasModel(mergedConnections[name], alias)));
|
|
32207
|
-
const
|
|
32219
|
+
const unnamed = harnessNamed.filter((name) => !configNames(writtenHarnesses, inheritedHarnesses, name, alias));
|
|
32220
|
+
const harnessNames = unnamed.filter((name) => !ownModels.harnesses.has(name));
|
|
32221
|
+
for (const name of unnamed.filter((n) => ownModels.harnesses.has(n) && !notedOwn.has(`${column}:${n}`))) {
|
|
32222
|
+
notedOwn.add(`${column}:${name}`);
|
|
32223
|
+
notes2.push(`models.json (${column === "*" ? "all" : column}): harness "${name}" has a model of its own, which names every alias, so the column is not carried over.`);
|
|
32224
|
+
}
|
|
32208
32225
|
if (connectionNames.length === 0 && harnessNames.length === 0) {
|
|
32209
32226
|
const keptByConfig = candidates.some((name) => configNames(writtenConnections, inheritedConnections, name, alias)) || harnessNamed.some((name) => configNames(writtenHarnesses, inheritedHarnesses, name, alias));
|
|
32210
32227
|
if (keptByConfig)
|
|
@@ -32264,15 +32281,23 @@ function implicitKeyVariables(name, defaults) {
|
|
|
32264
32281
|
const own2 = `AKM_ENGINE_${name.toUpperCase().replaceAll("-", "_")}_API_KEY`;
|
|
32265
32282
|
return name === str(defaults.llmEngine) ? [own2, "AKM_LLM_API_KEY"] : [own2];
|
|
32266
32283
|
}
|
|
32267
|
-
function runtimeEngine(name, engine, converted, conversion) {
|
|
32268
|
-
converted.runtimes.set(name,
|
|
32269
|
-
|
|
32270
|
-
}
|
|
32271
|
-
|
|
32272
|
-
|
|
32284
|
+
function runtimeEngine(name, engine, llmEngine, converted, conversion) {
|
|
32285
|
+
converted.runtimes.set(name, llmEngine);
|
|
32286
|
+
const dropped = ["model", "timeoutMs", "workspace", "bin", "agent"].filter((key) => engine[key] !== undefined);
|
|
32287
|
+
const gone = dropped.length === 0 ? "" : `; its ${dropped.join(", ")} ${dropped.length === 1 ? "is" : "are"} dropped`;
|
|
32288
|
+
conversion.notes.push(`engines.${name}: opencode-sdk over llmEngine "${llmEngine}" is akm's own runtime over connection "${llmEngine}" now, with no entry of its own${gone}.`);
|
|
32289
|
+
}
|
|
32290
|
+
function agentEngineToHarness(name, engine, converted, conversion) {
|
|
32291
|
+
const sdk = engine.platform === "opencode-sdk";
|
|
32292
|
+
const harness = { platform: sdk ? "opencode" : engine.platform };
|
|
32293
|
+
if (sdk)
|
|
32294
|
+
converted.sdkHarnesses.add(name);
|
|
32273
32295
|
for (const key of ["bin", "args", "workspace", "agent", "timeoutMs"])
|
|
32274
|
-
if (engine[key] !== undefined)
|
|
32296
|
+
if (engine[key] !== undefined && !(sdk && key === "args"))
|
|
32275
32297
|
harness[key] = engine[key];
|
|
32298
|
+
if (sdk && engine.args !== undefined) {
|
|
32299
|
+
conversion.notes.push(`engines.${name}: args is dropped. 0.9 did not pass it to OpenCode, and the opencode harness would pass it in place of \`run\`.`);
|
|
32300
|
+
}
|
|
32276
32301
|
const model = str(engine.model);
|
|
32277
32302
|
if (model !== undefined)
|
|
32278
32303
|
converted.ownModelOf.push({ kind: "harnesses", engine: name, model });
|
|
@@ -32323,6 +32348,7 @@ function convertEngines(engines, defaults, env, conversion) {
|
|
|
32323
32348
|
connections: {},
|
|
32324
32349
|
harnesses: {},
|
|
32325
32350
|
runtimes: new Map,
|
|
32351
|
+
sdkHarnesses: new Set,
|
|
32326
32352
|
keyHolders: [],
|
|
32327
32353
|
ownModelOf: []
|
|
32328
32354
|
};
|
|
@@ -32332,12 +32358,13 @@ function convertEngines(engines, defaults, env, conversion) {
|
|
|
32332
32358
|
const unknown2 = Object.keys(engine).filter((k) => !(engine.kind === "agent" ? AGENT_ENGINE_KEYS : LLM_ENGINE_KEYS).has(k));
|
|
32333
32359
|
if (unknown2.length > 0)
|
|
32334
32360
|
conversion.notes.push(`engines.${name}: dropped ${unknown2.join(", ")}, which akm does not read.`);
|
|
32361
|
+
const llmEngine = str(engine.llmEngine);
|
|
32335
32362
|
if (engine.kind !== "agent")
|
|
32336
32363
|
llmEngineToConnection(name, engine, defaults, env, converted, conversion);
|
|
32337
|
-
else if (engine.platform === "opencode-sdk")
|
|
32338
|
-
runtimeEngine(name, engine, converted, conversion);
|
|
32364
|
+
else if (engine.platform === "opencode-sdk" && llmEngine !== undefined)
|
|
32365
|
+
runtimeEngine(name, engine, llmEngine, converted, conversion);
|
|
32339
32366
|
else
|
|
32340
|
-
agentEngineToHarness(name, engine, converted);
|
|
32367
|
+
agentEngineToHarness(name, engine, converted, conversion);
|
|
32341
32368
|
}
|
|
32342
32369
|
return converted;
|
|
32343
32370
|
}
|
|
@@ -32355,11 +32382,21 @@ function renameMap(names, taken, from) {
|
|
|
32355
32382
|
}
|
|
32356
32383
|
return (name) => moved.get(name) ?? name;
|
|
32357
32384
|
}
|
|
32385
|
+
function agentWorkMoved(defaultEngine, runtimes, harness) {
|
|
32386
|
+
if (defaultEngine !== undefined) {
|
|
32387
|
+
return runtimes.has(defaultEngine) && harness !== undefined ? `Agent work ran on akm's own runtime (engines.${defaultEngine}); with the harness "${harness}" configured it now runs there. Remove that harness to keep agent work on akm's runtime.` : undefined;
|
|
32388
|
+
}
|
|
32389
|
+
const ran = "Without defaults.engine, agent work ran on your own OpenCode (the implicit fallback), when it was installed";
|
|
32390
|
+
return harness !== undefined ? `${ran}; with the harness "${harness}" configured it now runs there.` : `${ran}; it now runs on akm's own runtime. To keep it on your OpenCode, enable the harness: \`akm setup --harness opencode\`.`;
|
|
32391
|
+
}
|
|
32358
32392
|
function nameDefaults(defaults, converted, conversion, written) {
|
|
32359
|
-
const { connections, harnesses, runtimes, keyHolders } = converted;
|
|
32360
|
-
const
|
|
32393
|
+
const { connections, harnesses, runtimes, sdkHarnesses, keyHolders } = converted;
|
|
32394
|
+
const implicit = sdkHarnesses.has(IMPLICIT_AGENT_ENGINE) || runtimes.has(IMPLICIT_AGENT_ENGINE);
|
|
32395
|
+
const defaultEngine = str(defaults.engine) ?? (implicit ? IMPLICIT_AGENT_ENGINE : undefined);
|
|
32396
|
+
const modelWorkEngine = str(defaults.llmEngine);
|
|
32361
32397
|
const runtimeLlm = defaultEngine === undefined ? undefined : runtimes.get(defaultEngine);
|
|
32362
|
-
const
|
|
32398
|
+
const modelWorkRuntimeLlm = modelWorkEngine === undefined ? undefined : runtimes.get(modelWorkEngine);
|
|
32399
|
+
const defaultConnection = [modelWorkEngine, modelWorkRuntimeLlm, defaultEngine, runtimeLlm].find((n) => n !== undefined && (n in connections));
|
|
32363
32400
|
const defaultHarness = defaultEngine !== undefined && defaultEngine in harnesses && Object.keys(harnesses).length > 1 ? defaultEngine : undefined;
|
|
32364
32401
|
const connectionName = renameMap(Object.keys(connections), Object.keys(written.connections), defaultConnection);
|
|
32365
32402
|
const harnessName = renameMap(Object.keys(harnesses), Object.keys(written.harnesses), defaultHarness);
|
|
@@ -32368,9 +32405,16 @@ function nameDefaults(defaults, converted, conversion, written) {
|
|
|
32368
32405
|
connections: renamed(connections, connectionName),
|
|
32369
32406
|
harnesses: renamed(harnesses, harnessName)
|
|
32370
32407
|
};
|
|
32371
|
-
const defaultHarnessName =
|
|
32372
|
-
|
|
32373
|
-
|
|
32408
|
+
const defaultHarnessName = defaultName(named.harnesses);
|
|
32409
|
+
const hasEngines = Object.keys(connections).length + Object.keys(harnesses).length + runtimes.size > 0;
|
|
32410
|
+
const moved = hasEngines ? agentWorkMoved(defaultEngine, runtimes, defaultHarnessName) : undefined;
|
|
32411
|
+
if (moved !== undefined)
|
|
32412
|
+
conversion.notes.push(moved);
|
|
32413
|
+
if (modelWorkEngine !== undefined && modelWorkEngine in harnesses) {
|
|
32414
|
+
const now = harnessName(modelWorkEngine);
|
|
32415
|
+
if (defaultName({ ...named.connections, ...written.connections }) !== undefined || defaultHarnessName !== now) {
|
|
32416
|
+
conversion.notes.push(`defaults.llmEngine "${modelWorkEngine}" named an agent engine, which ran akm's model work. Model work now runs on the default connection, else the default harness; to keep it on the harness "${now}", set improve.harness to it.`);
|
|
32417
|
+
}
|
|
32374
32418
|
}
|
|
32375
32419
|
for (const [kind, rename] of [
|
|
32376
32420
|
["connections", connectionName],
|
|
@@ -32382,10 +32426,9 @@ function nameDefaults(defaults, converted, conversion, written) {
|
|
|
32382
32426
|
conversion.notes.push(`engines.default is now ${kind}.${aside}, and "default" names another engine: an engine: default key is rewritten by \`akm migrate apply\` where it can be, but a script or scheduled command that passes --engine default now reaches the new "default"; change it to the name ${aside}.`);
|
|
32383
32427
|
}
|
|
32384
32428
|
const target = (engine) => {
|
|
32385
|
-
|
|
32386
|
-
|
|
32387
|
-
return runtime
|
|
32388
|
-
}
|
|
32429
|
+
const runtime = runtimes.get(engine);
|
|
32430
|
+
if (runtime !== undefined)
|
|
32431
|
+
return runtime in connections ? { connection: connectionName(runtime) } : undefined;
|
|
32389
32432
|
if (engine in harnesses)
|
|
32390
32433
|
return { harness: harnessName(engine) };
|
|
32391
32434
|
if (engine in connections)
|
|
@@ -32397,7 +32440,7 @@ function nameDefaults(defaults, converted, conversion, written) {
|
|
|
32397
32440
|
connection: connectionName(engine),
|
|
32398
32441
|
field
|
|
32399
32442
|
}));
|
|
32400
|
-
return { defaultConnection, defaultHarness, connectionName, harnessName, ...named, keys, target };
|
|
32443
|
+
return { defaultEngine, defaultConnection, defaultHarness, connectionName, harnessName, ...named, keys, target };
|
|
32401
32444
|
}
|
|
32402
32445
|
function mergeWritten(out, naming) {
|
|
32403
32446
|
for (const [name, harness] of Object.entries(naming.harnesses)) {
|
|
@@ -32416,6 +32459,19 @@ function ownModelsOf(converted, naming) {
|
|
|
32416
32459
|
}
|
|
32417
32460
|
return ownModels;
|
|
32418
32461
|
}
|
|
32462
|
+
function modelWorkTarget(defaults, naming, merged, inherited, conversion) {
|
|
32463
|
+
const connection = defaultName({ ...inherited?.connections, ...merged.connections });
|
|
32464
|
+
if (connection !== undefined)
|
|
32465
|
+
return { connection };
|
|
32466
|
+
const harness = defaultName({ ...inherited?.harnesses, ...merged.harnesses });
|
|
32467
|
+
const entry = harness === undefined ? undefined : merged.harnesses[harness];
|
|
32468
|
+
if (harness === undefined || !isRecord(entry))
|
|
32469
|
+
return;
|
|
32470
|
+
if (str(defaults.llmEngine) === undefined && harness in naming.harnesses && entry.modelWork === undefined) {
|
|
32471
|
+
conversion.notes.push(`harnesses.${harness}: akm's own model work (improve, index passes, extraction, judges) now runs on this harness, the default for it with no connection. Without defaults.llmEngine, 0.9 ran none of it unless a setting named an engine (a workflow gate's judge ran on defaults.engine). To keep the 0.9 behaviour, set \`modelWork: false\` on this harness: a call that names it still runs there, but a workflow gate's judge then needs a connection (\`akm setup --endpoint URL\`).`);
|
|
32472
|
+
}
|
|
32473
|
+
return entry.modelWork === false ? undefined : { harness };
|
|
32474
|
+
}
|
|
32419
32475
|
function convertEngineConfig(raw, options = {}) {
|
|
32420
32476
|
const out = structuredClone(raw);
|
|
32421
32477
|
const engines = asDict(out.engines);
|
|
@@ -32438,7 +32494,8 @@ function convertEngineConfig(raw, options = {}) {
|
|
|
32438
32494
|
written: { connections: asDict(out.connections), harnesses: asDict(out.harnesses) },
|
|
32439
32495
|
inherited: { connections: options.inherited?.connections ?? {}, harnesses: options.inherited?.harnesses ?? {} },
|
|
32440
32496
|
renamed: {
|
|
32441
|
-
runtime: [...converted.runtimes.values()].filter((name) =>
|
|
32497
|
+
runtime: [...converted.runtimes.values()].filter((name) => (name in converted.connections)).map((name) => naming.connectionName(name)),
|
|
32498
|
+
sdkHarness: [...converted.sdkHarnesses].map((name) => naming.harnessName(name)),
|
|
32442
32499
|
connection: (engine) => (engine in converted.connections) ? naming.connectionName(engine) : undefined
|
|
32443
32500
|
}
|
|
32444
32501
|
});
|
|
@@ -32448,7 +32505,8 @@ function convertEngineConfig(raw, options = {}) {
|
|
|
32448
32505
|
if (isRecord(improve))
|
|
32449
32506
|
moveStrategyExecution(improve, conversion, retarget);
|
|
32450
32507
|
improveStrategyDefault(out, defaults, improve);
|
|
32451
|
-
|
|
32508
|
+
const judge = modelWorkTarget(defaults, naming, merged, options.inherited, conversion);
|
|
32509
|
+
dropJudgeEngine(out, conversion, naming.target, naming.defaultEngine, judge);
|
|
32452
32510
|
convertIndexEngines(out, conversion, retarget);
|
|
32453
32511
|
const config2 = {};
|
|
32454
32512
|
let placed = false;
|
|
@@ -32479,7 +32537,7 @@ function convertEngineConfig(raw, options = {}) {
|
|
|
32479
32537
|
targets
|
|
32480
32538
|
};
|
|
32481
32539
|
}
|
|
32482
|
-
var LLM_ENGINE_KEYS, AGENT_ENGINE_KEYS, CARRIED;
|
|
32540
|
+
var LLM_ENGINE_KEYS, AGENT_ENGINE_KEYS, CARRIED, defaultName = (entries) => ("default" in entries) ? "default" : Object.keys(entries).length === 1 ? Object.keys(entries)[0] : undefined, IMPLICIT_AGENT_ENGINE = "opencode-sdk";
|
|
32483
32541
|
var init_convert_engines = __esm(() => {
|
|
32484
32542
|
init_common();
|
|
32485
32543
|
init_convert_engine_references();
|
|
@@ -30475,6 +30475,7 @@ function modelWorkConfig() {
|
|
|
30475
30475
|
}
|
|
30476
30476
|
const config2 = {
|
|
30477
30477
|
...user,
|
|
30478
|
+
plugins: [...Array.isArray(user?.plugins) ? user.plugins : [], WITHOUT_BROWSER_PLUGIN],
|
|
30478
30479
|
agents: { ...asRecord(user?.agents), [MODEL_WORK_AGENT]: MODEL_WORK_AGENT_DEFINITION }
|
|
30479
30480
|
};
|
|
30480
30481
|
const legacy = asRecord(user?.agent);
|
|
@@ -30507,7 +30508,7 @@ function withEnvReferences(content) {
|
|
|
30507
30508
|
return replaced(true);
|
|
30508
30509
|
}
|
|
30509
30510
|
}
|
|
30510
|
-
var MODEL_WORK_AGENT = "akm-model-work", MODEL_WORK_AGENT_DEFINITION, CONFIG_CONTENT_ENV = "OPENCODE_CONFIG_CONTENT", NO_FREE_MODELS, opencodeBuilder;
|
|
30511
|
+
var MODEL_WORK_AGENT = "akm-model-work", MODEL_WORK_AGENT_DEFINITION, CONFIG_CONTENT_ENV = "OPENCODE_CONFIG_CONTENT", WITHOUT_BROWSER_PLUGIN = "-opencode.browser", NO_FREE_MODELS, opencodeBuilder;
|
|
30511
30512
|
var init_agent_builder = __esm(() => {
|
|
30512
30513
|
init_common();
|
|
30513
30514
|
init_warn();
|
|
@@ -32113,13 +32114,22 @@ function improveStrategyDefault(out, defaults, improve) {
|
|
|
32113
32114
|
out.improve = { ...isRecord(improve) ? improve : {} };
|
|
32114
32115
|
out.improve.strategy ??= defaults.improveStrategy;
|
|
32115
32116
|
}
|
|
32116
|
-
function dropJudgeEngine(out, conversion) {
|
|
32117
|
+
function dropJudgeEngine(out, conversion, target, defaultEngine, judge) {
|
|
32117
32118
|
const workflow = out.workflow;
|
|
32118
|
-
|
|
32119
|
-
|
|
32120
|
-
|
|
32121
|
-
|
|
32122
|
-
|
|
32119
|
+
const named = isRecord(workflow) && "judgeEngine" in workflow;
|
|
32120
|
+
const engine = named ? str(workflow.judgeEngine) : defaultEngine;
|
|
32121
|
+
if (named) {
|
|
32122
|
+
delete workflow.judgeEngine;
|
|
32123
|
+
conversion.changed = true;
|
|
32124
|
+
}
|
|
32125
|
+
const became = engine === undefined ? undefined : target(engine);
|
|
32126
|
+
const stays = became !== undefined && judge !== undefined && isDeepStrictEqual(became, judge);
|
|
32127
|
+
const kind = judge === undefined ? undefined : ("connection" in judge) ? "connection" : "harness";
|
|
32128
|
+
if (named) {
|
|
32129
|
+
conversion.notes.push(stays ? `workflow.judgeEngine: "${engine}" is the default ${kind}, where a gate's judge runs now; the setting is dropped.` : `workflow.judgeEngine${engine === undefined ? "" : ` "${engine}"`}: dropped. A gate's judge runs on the default connection, else the default harness, so a judge that ran on another engine has moved; to keep it, make that engine the default.`);
|
|
32130
|
+
} else if (became !== undefined && judge !== undefined && !stays) {
|
|
32131
|
+
conversion.notes.push(`workflow: with no workflow.judgeEngine, a gate's judge ran on the default engine "${engine}"; it is model work now and runs on the default ${kind}, "${"connection" in judge ? judge.connection : judge.harness}".`);
|
|
32132
|
+
}
|
|
32123
32133
|
}
|
|
32124
32134
|
function convertIndexEngines(out, conversion, retarget) {
|
|
32125
32135
|
const index = out.index;
|
|
@@ -32186,6 +32196,8 @@ function foldModelsOverlay(modelsOverlay, fold) {
|
|
|
32186
32196
|
const writtenHarnesses = written.harnesses;
|
|
32187
32197
|
const configNames = (own2, base, name, alias) => hasModel(own2[name], alias) || hasModel(base[name], alias);
|
|
32188
32198
|
const platformOf = (name) => String((mergedHarnesses[name] ?? inheritedHarnesses[name])?.platform ?? name);
|
|
32199
|
+
const columnOf = (name) => renamed.sdkHarness.includes(name) ? "opencode-sdk" : platformOf(name);
|
|
32200
|
+
const notedOwn = new Set;
|
|
32189
32201
|
let folded = false;
|
|
32190
32202
|
for (const { alias, column, profile } of overlayRows(modelsOverlay)) {
|
|
32191
32203
|
const p = typeof profile === "string" ? { model: profile } : isRecord(profile) ? profile : {};
|
|
@@ -32197,13 +32209,18 @@ function foldModelsOverlay(modelsOverlay, fold) {
|
|
|
32197
32209
|
continue;
|
|
32198
32210
|
}
|
|
32199
32211
|
const candidates = column === "*" ? [...new Set([...Object.keys(mergedConnections), ...Object.keys(inheritedConnections)])] : column === "opencode-sdk" ? [...renamed.runtime] : renamed.connection(column) !== undefined ? [renamed.connection(column)] : (column in writtenConnections) || (column in inheritedConnections) ? [column] : [];
|
|
32200
|
-
const harnessNamed = [...new Set([...Object.keys(mergedHarnesses), ...Object.keys(inheritedHarnesses)])].filter((name) =>
|
|
32212
|
+
const harnessNamed = [...new Set([...Object.keys(mergedHarnesses), ...Object.keys(inheritedHarnesses)])].filter((name) => columnOf(name) === column);
|
|
32201
32213
|
if (candidates.length === 0 && harnessNamed.length === 0) {
|
|
32202
32214
|
notes2.push(`${where}: names no configured connection or harness, so it is not carried over.`);
|
|
32203
32215
|
continue;
|
|
32204
32216
|
}
|
|
32205
32217
|
const connectionNames = candidates.filter((name) => !configNames(writtenConnections, inheritedConnections, name, alias) && !(column === "*" && hasModel(mergedConnections[name], alias)));
|
|
32206
|
-
const
|
|
32218
|
+
const unnamed = harnessNamed.filter((name) => !configNames(writtenHarnesses, inheritedHarnesses, name, alias));
|
|
32219
|
+
const harnessNames = unnamed.filter((name) => !ownModels.harnesses.has(name));
|
|
32220
|
+
for (const name of unnamed.filter((n) => ownModels.harnesses.has(n) && !notedOwn.has(`${column}:${n}`))) {
|
|
32221
|
+
notedOwn.add(`${column}:${name}`);
|
|
32222
|
+
notes2.push(`models.json (${column === "*" ? "all" : column}): harness "${name}" has a model of its own, which names every alias, so the column is not carried over.`);
|
|
32223
|
+
}
|
|
32207
32224
|
if (connectionNames.length === 0 && harnessNames.length === 0) {
|
|
32208
32225
|
const keptByConfig = candidates.some((name) => configNames(writtenConnections, inheritedConnections, name, alias)) || harnessNamed.some((name) => configNames(writtenHarnesses, inheritedHarnesses, name, alias));
|
|
32209
32226
|
if (keptByConfig)
|
|
@@ -32263,15 +32280,23 @@ function implicitKeyVariables(name, defaults) {
|
|
|
32263
32280
|
const own2 = `AKM_ENGINE_${name.toUpperCase().replaceAll("-", "_")}_API_KEY`;
|
|
32264
32281
|
return name === str(defaults.llmEngine) ? [own2, "AKM_LLM_API_KEY"] : [own2];
|
|
32265
32282
|
}
|
|
32266
|
-
function runtimeEngine(name, engine, converted, conversion) {
|
|
32267
|
-
converted.runtimes.set(name,
|
|
32268
|
-
|
|
32269
|
-
}
|
|
32270
|
-
|
|
32271
|
-
|
|
32283
|
+
function runtimeEngine(name, engine, llmEngine, converted, conversion) {
|
|
32284
|
+
converted.runtimes.set(name, llmEngine);
|
|
32285
|
+
const dropped = ["model", "timeoutMs", "workspace", "bin", "agent"].filter((key) => engine[key] !== undefined);
|
|
32286
|
+
const gone = dropped.length === 0 ? "" : `; its ${dropped.join(", ")} ${dropped.length === 1 ? "is" : "are"} dropped`;
|
|
32287
|
+
conversion.notes.push(`engines.${name}: opencode-sdk over llmEngine "${llmEngine}" is akm's own runtime over connection "${llmEngine}" now, with no entry of its own${gone}.`);
|
|
32288
|
+
}
|
|
32289
|
+
function agentEngineToHarness(name, engine, converted, conversion) {
|
|
32290
|
+
const sdk = engine.platform === "opencode-sdk";
|
|
32291
|
+
const harness = { platform: sdk ? "opencode" : engine.platform };
|
|
32292
|
+
if (sdk)
|
|
32293
|
+
converted.sdkHarnesses.add(name);
|
|
32272
32294
|
for (const key of ["bin", "args", "workspace", "agent", "timeoutMs"])
|
|
32273
|
-
if (engine[key] !== undefined)
|
|
32295
|
+
if (engine[key] !== undefined && !(sdk && key === "args"))
|
|
32274
32296
|
harness[key] = engine[key];
|
|
32297
|
+
if (sdk && engine.args !== undefined) {
|
|
32298
|
+
conversion.notes.push(`engines.${name}: args is dropped. 0.9 did not pass it to OpenCode, and the opencode harness would pass it in place of \`run\`.`);
|
|
32299
|
+
}
|
|
32275
32300
|
const model = str(engine.model);
|
|
32276
32301
|
if (model !== undefined)
|
|
32277
32302
|
converted.ownModelOf.push({ kind: "harnesses", engine: name, model });
|
|
@@ -32322,6 +32347,7 @@ function convertEngines(engines, defaults, env, conversion) {
|
|
|
32322
32347
|
connections: {},
|
|
32323
32348
|
harnesses: {},
|
|
32324
32349
|
runtimes: new Map,
|
|
32350
|
+
sdkHarnesses: new Set,
|
|
32325
32351
|
keyHolders: [],
|
|
32326
32352
|
ownModelOf: []
|
|
32327
32353
|
};
|
|
@@ -32331,12 +32357,13 @@ function convertEngines(engines, defaults, env, conversion) {
|
|
|
32331
32357
|
const unknown2 = Object.keys(engine).filter((k) => !(engine.kind === "agent" ? AGENT_ENGINE_KEYS : LLM_ENGINE_KEYS).has(k));
|
|
32332
32358
|
if (unknown2.length > 0)
|
|
32333
32359
|
conversion.notes.push(`engines.${name}: dropped ${unknown2.join(", ")}, which akm does not read.`);
|
|
32360
|
+
const llmEngine = str(engine.llmEngine);
|
|
32334
32361
|
if (engine.kind !== "agent")
|
|
32335
32362
|
llmEngineToConnection(name, engine, defaults, env, converted, conversion);
|
|
32336
|
-
else if (engine.platform === "opencode-sdk")
|
|
32337
|
-
runtimeEngine(name, engine, converted, conversion);
|
|
32363
|
+
else if (engine.platform === "opencode-sdk" && llmEngine !== undefined)
|
|
32364
|
+
runtimeEngine(name, engine, llmEngine, converted, conversion);
|
|
32338
32365
|
else
|
|
32339
|
-
agentEngineToHarness(name, engine, converted);
|
|
32366
|
+
agentEngineToHarness(name, engine, converted, conversion);
|
|
32340
32367
|
}
|
|
32341
32368
|
return converted;
|
|
32342
32369
|
}
|
|
@@ -32354,11 +32381,21 @@ function renameMap(names, taken, from) {
|
|
|
32354
32381
|
}
|
|
32355
32382
|
return (name) => moved.get(name) ?? name;
|
|
32356
32383
|
}
|
|
32384
|
+
function agentWorkMoved(defaultEngine, runtimes, harness) {
|
|
32385
|
+
if (defaultEngine !== undefined) {
|
|
32386
|
+
return runtimes.has(defaultEngine) && harness !== undefined ? `Agent work ran on akm's own runtime (engines.${defaultEngine}); with the harness "${harness}" configured it now runs there. Remove that harness to keep agent work on akm's runtime.` : undefined;
|
|
32387
|
+
}
|
|
32388
|
+
const ran = "Without defaults.engine, agent work ran on your own OpenCode (the implicit fallback), when it was installed";
|
|
32389
|
+
return harness !== undefined ? `${ran}; with the harness "${harness}" configured it now runs there.` : `${ran}; it now runs on akm's own runtime. To keep it on your OpenCode, enable the harness: \`akm setup --harness opencode\`.`;
|
|
32390
|
+
}
|
|
32357
32391
|
function nameDefaults(defaults, converted, conversion, written) {
|
|
32358
|
-
const { connections, harnesses, runtimes, keyHolders } = converted;
|
|
32359
|
-
const
|
|
32392
|
+
const { connections, harnesses, runtimes, sdkHarnesses, keyHolders } = converted;
|
|
32393
|
+
const implicit = sdkHarnesses.has(IMPLICIT_AGENT_ENGINE) || runtimes.has(IMPLICIT_AGENT_ENGINE);
|
|
32394
|
+
const defaultEngine = str(defaults.engine) ?? (implicit ? IMPLICIT_AGENT_ENGINE : undefined);
|
|
32395
|
+
const modelWorkEngine = str(defaults.llmEngine);
|
|
32360
32396
|
const runtimeLlm = defaultEngine === undefined ? undefined : runtimes.get(defaultEngine);
|
|
32361
|
-
const
|
|
32397
|
+
const modelWorkRuntimeLlm = modelWorkEngine === undefined ? undefined : runtimes.get(modelWorkEngine);
|
|
32398
|
+
const defaultConnection = [modelWorkEngine, modelWorkRuntimeLlm, defaultEngine, runtimeLlm].find((n) => n !== undefined && (n in connections));
|
|
32362
32399
|
const defaultHarness = defaultEngine !== undefined && defaultEngine in harnesses && Object.keys(harnesses).length > 1 ? defaultEngine : undefined;
|
|
32363
32400
|
const connectionName = renameMap(Object.keys(connections), Object.keys(written.connections), defaultConnection);
|
|
32364
32401
|
const harnessName = renameMap(Object.keys(harnesses), Object.keys(written.harnesses), defaultHarness);
|
|
@@ -32367,9 +32404,16 @@ function nameDefaults(defaults, converted, conversion, written) {
|
|
|
32367
32404
|
connections: renamed(connections, connectionName),
|
|
32368
32405
|
harnesses: renamed(harnesses, harnessName)
|
|
32369
32406
|
};
|
|
32370
|
-
const defaultHarnessName =
|
|
32371
|
-
|
|
32372
|
-
|
|
32407
|
+
const defaultHarnessName = defaultName(named.harnesses);
|
|
32408
|
+
const hasEngines = Object.keys(connections).length + Object.keys(harnesses).length + runtimes.size > 0;
|
|
32409
|
+
const moved = hasEngines ? agentWorkMoved(defaultEngine, runtimes, defaultHarnessName) : undefined;
|
|
32410
|
+
if (moved !== undefined)
|
|
32411
|
+
conversion.notes.push(moved);
|
|
32412
|
+
if (modelWorkEngine !== undefined && modelWorkEngine in harnesses) {
|
|
32413
|
+
const now = harnessName(modelWorkEngine);
|
|
32414
|
+
if (defaultName({ ...named.connections, ...written.connections }) !== undefined || defaultHarnessName !== now) {
|
|
32415
|
+
conversion.notes.push(`defaults.llmEngine "${modelWorkEngine}" named an agent engine, which ran akm's model work. Model work now runs on the default connection, else the default harness; to keep it on the harness "${now}", set improve.harness to it.`);
|
|
32416
|
+
}
|
|
32373
32417
|
}
|
|
32374
32418
|
for (const [kind, rename] of [
|
|
32375
32419
|
["connections", connectionName],
|
|
@@ -32381,10 +32425,9 @@ function nameDefaults(defaults, converted, conversion, written) {
|
|
|
32381
32425
|
conversion.notes.push(`engines.default is now ${kind}.${aside}, and "default" names another engine: an engine: default key is rewritten by \`akm migrate apply\` where it can be, but a script or scheduled command that passes --engine default now reaches the new "default"; change it to the name ${aside}.`);
|
|
32382
32426
|
}
|
|
32383
32427
|
const target = (engine) => {
|
|
32384
|
-
|
|
32385
|
-
|
|
32386
|
-
return runtime
|
|
32387
|
-
}
|
|
32428
|
+
const runtime = runtimes.get(engine);
|
|
32429
|
+
if (runtime !== undefined)
|
|
32430
|
+
return runtime in connections ? { connection: connectionName(runtime) } : undefined;
|
|
32388
32431
|
if (engine in harnesses)
|
|
32389
32432
|
return { harness: harnessName(engine) };
|
|
32390
32433
|
if (engine in connections)
|
|
@@ -32396,7 +32439,7 @@ function nameDefaults(defaults, converted, conversion, written) {
|
|
|
32396
32439
|
connection: connectionName(engine),
|
|
32397
32440
|
field
|
|
32398
32441
|
}));
|
|
32399
|
-
return { defaultConnection, defaultHarness, connectionName, harnessName, ...named, keys, target };
|
|
32442
|
+
return { defaultEngine, defaultConnection, defaultHarness, connectionName, harnessName, ...named, keys, target };
|
|
32400
32443
|
}
|
|
32401
32444
|
function mergeWritten(out, naming) {
|
|
32402
32445
|
for (const [name, harness] of Object.entries(naming.harnesses)) {
|
|
@@ -32415,6 +32458,19 @@ function ownModelsOf(converted, naming) {
|
|
|
32415
32458
|
}
|
|
32416
32459
|
return ownModels;
|
|
32417
32460
|
}
|
|
32461
|
+
function modelWorkTarget(defaults, naming, merged, inherited, conversion) {
|
|
32462
|
+
const connection = defaultName({ ...inherited?.connections, ...merged.connections });
|
|
32463
|
+
if (connection !== undefined)
|
|
32464
|
+
return { connection };
|
|
32465
|
+
const harness = defaultName({ ...inherited?.harnesses, ...merged.harnesses });
|
|
32466
|
+
const entry = harness === undefined ? undefined : merged.harnesses[harness];
|
|
32467
|
+
if (harness === undefined || !isRecord(entry))
|
|
32468
|
+
return;
|
|
32469
|
+
if (str(defaults.llmEngine) === undefined && harness in naming.harnesses && entry.modelWork === undefined) {
|
|
32470
|
+
conversion.notes.push(`harnesses.${harness}: akm's own model work (improve, index passes, extraction, judges) now runs on this harness, the default for it with no connection. Without defaults.llmEngine, 0.9 ran none of it unless a setting named an engine (a workflow gate's judge ran on defaults.engine). To keep the 0.9 behaviour, set \`modelWork: false\` on this harness: a call that names it still runs there, but a workflow gate's judge then needs a connection (\`akm setup --endpoint URL\`).`);
|
|
32471
|
+
}
|
|
32472
|
+
return entry.modelWork === false ? undefined : { harness };
|
|
32473
|
+
}
|
|
32418
32474
|
function convertEngineConfig(raw, options = {}) {
|
|
32419
32475
|
const out = structuredClone(raw);
|
|
32420
32476
|
const engines = asDict(out.engines);
|
|
@@ -32437,7 +32493,8 @@ function convertEngineConfig(raw, options = {}) {
|
|
|
32437
32493
|
written: { connections: asDict(out.connections), harnesses: asDict(out.harnesses) },
|
|
32438
32494
|
inherited: { connections: options.inherited?.connections ?? {}, harnesses: options.inherited?.harnesses ?? {} },
|
|
32439
32495
|
renamed: {
|
|
32440
|
-
runtime: [...converted.runtimes.values()].filter((name) =>
|
|
32496
|
+
runtime: [...converted.runtimes.values()].filter((name) => (name in converted.connections)).map((name) => naming.connectionName(name)),
|
|
32497
|
+
sdkHarness: [...converted.sdkHarnesses].map((name) => naming.harnessName(name)),
|
|
32441
32498
|
connection: (engine) => (engine in converted.connections) ? naming.connectionName(engine) : undefined
|
|
32442
32499
|
}
|
|
32443
32500
|
});
|
|
@@ -32447,7 +32504,8 @@ function convertEngineConfig(raw, options = {}) {
|
|
|
32447
32504
|
if (isRecord(improve))
|
|
32448
32505
|
moveStrategyExecution(improve, conversion, retarget);
|
|
32449
32506
|
improveStrategyDefault(out, defaults, improve);
|
|
32450
|
-
|
|
32507
|
+
const judge = modelWorkTarget(defaults, naming, merged, options.inherited, conversion);
|
|
32508
|
+
dropJudgeEngine(out, conversion, naming.target, naming.defaultEngine, judge);
|
|
32451
32509
|
convertIndexEngines(out, conversion, retarget);
|
|
32452
32510
|
const config2 = {};
|
|
32453
32511
|
let placed = false;
|
|
@@ -32478,7 +32536,7 @@ function convertEngineConfig(raw, options = {}) {
|
|
|
32478
32536
|
targets
|
|
32479
32537
|
};
|
|
32480
32538
|
}
|
|
32481
|
-
var LLM_ENGINE_KEYS, AGENT_ENGINE_KEYS, CARRIED;
|
|
32539
|
+
var LLM_ENGINE_KEYS, AGENT_ENGINE_KEYS, CARRIED, defaultName = (entries) => ("default" in entries) ? "default" : Object.keys(entries).length === 1 ? Object.keys(entries)[0] : undefined, IMPLICIT_AGENT_ENGINE = "opencode-sdk";
|
|
32482
32540
|
var init_convert_engines = __esm(() => {
|
|
32483
32541
|
init_common();
|
|
32484
32542
|
init_convert_engine_references();
|
|
@@ -639,7 +639,8 @@ Agent programs are reachable by two execution paths, both behind
|
|
|
639
639
|
- `runAgent(profile, options)` is the single shell-out entry point. It owns
|
|
640
640
|
process spawn, captured/interactive stdio, hard timeout, and structured
|
|
641
641
|
failure reasons. The child's environment is the one akm runs in, with the
|
|
642
|
-
directories this akm resolved and the call's own variables set over it
|
|
642
|
+
directories this akm resolved and the call's own variables set over it, and
|
|
643
|
+
`PWD` naming the directory of a run given one, as `cd` sets it.
|
|
643
644
|
- The `opencode` harness is the user's installed OpenCode, both majors, through
|
|
644
645
|
`opencode run` with the prompt on stdin
|
|
645
646
|
(`src/integrations/harnesses/opencode/agent-builder.ts`). Their OpenCode owns
|
|
@@ -686,9 +687,14 @@ Agent programs are reachable by two execution paths, both behind
|
|
|
686
687
|
a JSON array: the executable alone when compiled, the runtime and the script
|
|
687
688
|
otherwise), the
|
|
688
689
|
connection's request fields are laid over each model request, with OpenCode's
|
|
689
|
-
own output cap taken off,
|
|
690
|
+
own output cap taken off, the variables akm set for the process (its
|
|
690
691
|
directories and its OpenCode settings) are put back to akm's own, or removed,
|
|
691
|
-
in the environment of the commands the agent runs
|
|
692
|
+
in the environment of the commands the agent runs, and a run whose model has
|
|
693
|
+
made the same tool call and been given the same result three turns in a row
|
|
694
|
+
adds a message to its next request that tells it so (a connection's
|
|
695
|
+
temperature below 0.7 is raised to 0.7 for that request), and fails before the
|
|
696
|
+
request that would follow if it makes the same call again (OpenCode has no such
|
|
697
|
+
check).
|
|
692
698
|
- The connection's key is in no environment: the inline config references it as
|
|
693
699
|
`{file:<data>/opencode-runtime/keys/<session>}`, a 0600 file written for the
|
|
694
700
|
run and removed after it.
|
|
@@ -346,7 +346,7 @@ tool call, releases OpenCode's claim on the session and leaves no process
|
|
|
346
346
|
behind. Agent work is the plain invocation, which OpenCode 2 runs through a
|
|
347
347
|
background service on one port for every `HOME`: those cases end the service
|
|
348
348
|
they start, skip when something else holds the port, and record that a stop ends
|
|
349
|
-
the `opencode` command and the service's turn (2.1.4) and leaves the service up.
|
|
349
|
+
the `opencode` command and the service's turn (2.1.4 and 2.2.0) and leaves the service up.
|
|
350
350
|
A provider defined only in the
|
|
351
351
|
user's `OPENCODE_CONFIG_CONTENT` works for agent work and model work alike. Run
|
|
352
352
|
it when changing the OpenCode builder or the subprocess kill ladder, and against
|
package/docs/migration/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Upgrade guides and per-release migration notes.
|
|
|
5
5
|
## Current
|
|
6
6
|
|
|
7
7
|
- [v0.9 -> v0.10 migration guide](v0.9-to-v0.10.md) -- Upgrade order for a 0.9.15+ install, every removed CLI spelling, strategy, config key and workflow feature with its replacement, changed `akm improve` defaults, the OpenCode plugins, and `0.10.YYMMNN` version numbers
|
|
8
|
-
- [v0.10.0 release note](release-notes/0.10.
|
|
8
|
+
- [v0.10.0 release note](release-notes/0.10.261019.md) -- Summary of the 0.10 series: the 0.9.15 version floor, `--shape`/`--target`/`help agents` removals, `default` and `consolidate` as the only built-in strategies, OpenCode 2, feedback-scaled ranking, and what is gone
|
|
9
9
|
- [Release notes index](release-notes/README.md) -- The short per-release notes `akm help migrate <version>` prints, with links to every bundled note
|
|
10
10
|
|
|
11
11
|
## Historical
|