@agentproto/driver-agent-cli 0.3.0 → 0.4.0
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-KHHRPQ2Q.mjs → chunk-L6BRNMVP.mjs} +175 -23
- package/dist/chunk-L6BRNMVP.mjs.map +1 -0
- package/dist/index.d.ts +12 -3
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/manifest/index.d.ts +2 -2
- package/dist/manifest/index.mjs +2 -2
- package/dist/{schema-Ds8jc9fL.d.ts → schema-L-2rEB1H.d.ts} +179 -1
- package/package.json +2 -2
- package/dist/chunk-KHHRPQ2Q.mjs.map +0 -1
|
@@ -164,6 +164,10 @@ var sessionSchema = z.object({
|
|
|
164
164
|
var modelsSchema = z.object({
|
|
165
165
|
default: z.string().optional(),
|
|
166
166
|
allowed: z.array(z.string()).optional(),
|
|
167
|
+
// Model-id patterns the adapter must never route to (case-insensitive,
|
|
168
|
+
// trailing `*` = prefix match). Enforced at compose time — see
|
|
169
|
+
// AgentCliModels.deny. Reserves premium providers for dedicated adapters.
|
|
170
|
+
deny: z.array(z.string()).optional(),
|
|
167
171
|
env: z.record(z.string(), z.string()).optional(),
|
|
168
172
|
// How a model is selected at session start: "config" (ACP
|
|
169
173
|
// set_config_option, default) | "command" (a `/model <id>` control turn,
|
|
@@ -190,8 +194,21 @@ var capabilitiesSchema = z.object({
|
|
|
190
194
|
var modeSchema = z.object({
|
|
191
195
|
id: z.string().regex(MODE_ID_PATTERN),
|
|
192
196
|
description: z.string().optional(),
|
|
197
|
+
bin_args_prepend: z.array(z.string()).optional(),
|
|
193
198
|
bin_args_append: z.array(z.string()).optional(),
|
|
194
|
-
env: z.record(z.string(), z.string()).optional()
|
|
199
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
200
|
+
// Env keys to DELETE from the spawn env (auth hygiene for gateway
|
|
201
|
+
// modes — see AgentCliMode.env_unset). Applied at the runtime merge
|
|
202
|
+
// point, not as a static set.
|
|
203
|
+
env_unset: z.array(z.string()).optional(),
|
|
204
|
+
// Honest support status surfaced to clients. Absent ⇒ "active".
|
|
205
|
+
status: z.enum(["active", "noop", "planned"]).optional(),
|
|
206
|
+
status_note: z.string().optional(),
|
|
207
|
+
// How the host activates this mode: "bin_args" (default, argv/env
|
|
208
|
+
// composed at spawn) | "config" (no CLI surface — forwarded to the ACP
|
|
209
|
+
// arm's connect({mode}) and applied via session/set_config_option
|
|
210
|
+
// configId:"mode", e.g. opencode).
|
|
211
|
+
apply: z.enum(["bin_args", "config"]).optional()
|
|
195
212
|
}).strict();
|
|
196
213
|
var optionSchema = z.object({
|
|
197
214
|
id: z.string().regex(OPTION_ID_PATTERN),
|
|
@@ -201,9 +218,14 @@ var optionSchema = z.object({
|
|
|
201
218
|
default: z.union([z.boolean(), z.number(), z.string()]).optional(),
|
|
202
219
|
min: z.number().int().optional(),
|
|
203
220
|
max: z.number().int().optional(),
|
|
221
|
+
bin_args_prepend: z.array(z.string()).optional(),
|
|
204
222
|
bin_args_template: z.array(z.string()).optional(),
|
|
205
223
|
bin_args_append_when_true: z.array(z.string()).optional(),
|
|
206
|
-
env: z.record(z.string(), z.string()).optional()
|
|
224
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
225
|
+
// Env keys to DELETE from the spawn env when this option is active
|
|
226
|
+
// (auth hygiene for value-bearing gateway options — see
|
|
227
|
+
// AgentCliOption.env_unset). Symmetric with modeSchema.env_unset.
|
|
228
|
+
env_unset: z.array(z.string()).optional()
|
|
207
229
|
}).strict().refine(
|
|
208
230
|
// type === "enum" REQUIRES an `enum` array. The JSON Schema enforces
|
|
209
231
|
// this via `if/then`; the zod side mirrors with a refine so both
|
|
@@ -211,6 +233,17 @@ var optionSchema = z.object({
|
|
|
211
233
|
(o) => o.type !== "enum" || Array.isArray(o.enum) && o.enum.length > 0,
|
|
212
234
|
{ message: "option.type === 'enum' requires a non-empty `enum` array" }
|
|
213
235
|
);
|
|
236
|
+
var presetSchema = z.object({
|
|
237
|
+
id: z.string().min(1),
|
|
238
|
+
label: z.string().min(1),
|
|
239
|
+
description: z.string().optional(),
|
|
240
|
+
schemaFlavor: z.enum(["anthropic", "openai"]),
|
|
241
|
+
baseUrl: z.string().min(1),
|
|
242
|
+
keyEnv: z.string().min(1),
|
|
243
|
+
scrubEnv: z.array(z.string()).optional(),
|
|
244
|
+
defaultModel: z.string().optional(),
|
|
245
|
+
homepage: z.string().optional()
|
|
246
|
+
}).strict();
|
|
214
247
|
var continuationStrategyIdSchema = z.enum(CONTINUATION_STRATEGY_IDS);
|
|
215
248
|
var continuationSchema = z.object({
|
|
216
249
|
default: continuationStrategyIdSchema,
|
|
@@ -266,6 +299,9 @@ var agentCliFrontmatterSchema = z.object({
|
|
|
266
299
|
capabilities: capabilitiesSchema.optional(),
|
|
267
300
|
modes: z.array(modeSchema).optional(),
|
|
268
301
|
options: z.array(optionSchema).optional(),
|
|
302
|
+
// AIP-45 gateway presets this adapter can drive (merged into the
|
|
303
|
+
// provider-preset catalog; built-in wins on id collision).
|
|
304
|
+
presets: z.array(presetSchema).optional(),
|
|
269
305
|
continuation: continuationSchema.optional(),
|
|
270
306
|
requires: z.object({
|
|
271
307
|
os: z.array(z.enum(["darwin", "linux", "windows"])).optional(),
|
|
@@ -406,7 +442,8 @@ function createAcpProtocolArm(options) {
|
|
|
406
442
|
cwd,
|
|
407
443
|
mcpServers: opts.mcpServers,
|
|
408
444
|
...opts.model ? { model: opts.model } : {},
|
|
409
|
-
...opts.effort ? { effort: opts.effort } : {}
|
|
445
|
+
...opts.effort ? { effort: opts.effort } : {},
|
|
446
|
+
...opts.mode ? { mode: opts.mode } : {}
|
|
410
447
|
});
|
|
411
448
|
}
|
|
412
449
|
},
|
|
@@ -493,22 +530,26 @@ function createPrintSession(opts) {
|
|
|
493
530
|
try {
|
|
494
531
|
if (!child.stdout)
|
|
495
532
|
throw new Error("print-arm: child has no stdout pipe");
|
|
496
|
-
const rl = createInterface({ input: child.stdout, crlfDelay: Infinity });
|
|
497
533
|
let capturedSessionId = "";
|
|
498
534
|
const mastraState = eventSchema === "mastra-jsonl" ? createMastraMapperState() : void 0;
|
|
499
|
-
|
|
500
|
-
|
|
535
|
+
const rl = createInterface({ input: child.stdout, crlfDelay: Infinity });
|
|
536
|
+
const queue = new EventQueue();
|
|
537
|
+
rl.on("line", (line) => {
|
|
538
|
+
if (!line.trim()) return;
|
|
501
539
|
let evt;
|
|
502
540
|
try {
|
|
503
541
|
evt = JSON.parse(line);
|
|
504
542
|
} catch {
|
|
505
|
-
|
|
543
|
+
return;
|
|
506
544
|
}
|
|
507
545
|
const csid = captureSessionId(evt, eventSchema);
|
|
508
546
|
if (csid) capturedSessionId = csid;
|
|
509
547
|
const sid = capturedSessionId || sessionId || "";
|
|
510
548
|
const mapped = mapEvent(evt, sid, stderrLines, eventSchema, mastraState);
|
|
511
|
-
if (
|
|
549
|
+
if (mapped) queue.push(mapped);
|
|
550
|
+
});
|
|
551
|
+
rl.once("close", () => queue.end());
|
|
552
|
+
for await (const mapped of queue) {
|
|
512
553
|
yield mapped;
|
|
513
554
|
}
|
|
514
555
|
const exitCode = await waitForExit(child);
|
|
@@ -774,6 +815,37 @@ function mapMastraEvent(evt, sessionId, stderrLines, state) {
|
|
|
774
815
|
}
|
|
775
816
|
};
|
|
776
817
|
}
|
|
818
|
+
// ── Token usage ─────────────────────────────────────────────
|
|
819
|
+
// Mastra Code DOES expose usage: its `AgentController` emits a native
|
|
820
|
+
// `usage_update` event ({ type: "usage_update", usage: TokenUsage })
|
|
821
|
+
// on every model step-finish — verified against @mastra/core 1.48.0's
|
|
822
|
+
// AgentControllerEvent union and its emit site
|
|
823
|
+
// (`this.#session.emit({ type: "usage_update", usage: stepUsage })`).
|
|
824
|
+
// `TokenUsage` carries `{ promptTokens, completionTokens, totalTokens }`.
|
|
825
|
+
// Map it to this repo's `usage_update` StreamEvent (the SAME shape
|
|
826
|
+
// claude-code emits over ACP) so mastracode sessions — both the print
|
|
827
|
+
// arm and the in-process arm, which share this mapper — carry token
|
|
828
|
+
// telemetry in the transcript. mastracode reports these cumulatively
|
|
829
|
+
// (its own headless `runMC` result-usage is last-write-wins over these
|
|
830
|
+
// events), and last-write-wins on the descriptor matches that. It
|
|
831
|
+
// carries no context-window size/used or per-turn cost here, so those
|
|
832
|
+
// stay 0 / absent (projectEvent guards on >0, never clobbering a real
|
|
833
|
+
// size).
|
|
834
|
+
case "usage_update": {
|
|
835
|
+
const usage = evt.usage;
|
|
836
|
+
const promptTokens = typeof usage?.promptTokens === "number" ? usage.promptTokens : void 0;
|
|
837
|
+
const completionTokens = typeof usage?.completionTokens === "number" ? usage.completionTokens : void 0;
|
|
838
|
+
if (promptTokens === void 0 && completionTokens === void 0)
|
|
839
|
+
return null;
|
|
840
|
+
return {
|
|
841
|
+
kind: "usage_update",
|
|
842
|
+
sessionId,
|
|
843
|
+
size: 0,
|
|
844
|
+
used: 0,
|
|
845
|
+
...promptTokens !== void 0 ? { tokensIn: promptTokens } : {},
|
|
846
|
+
...completionTokens !== void 0 ? { tokensOut: completionTokens } : {}
|
|
847
|
+
};
|
|
848
|
+
}
|
|
777
849
|
// ── Shell output (tool-like) ────────────────────────────────
|
|
778
850
|
case "shell_output":
|
|
779
851
|
return typeof evt.output === "string" ? {
|
|
@@ -794,6 +866,45 @@ function mapMastraEvent(evt, sessionId, stderrLines, state) {
|
|
|
794
866
|
return null;
|
|
795
867
|
}
|
|
796
868
|
}
|
|
869
|
+
var QUEUE_HIGH_WATER_MARK = 1e4;
|
|
870
|
+
var EventQueue = class {
|
|
871
|
+
buffer = [];
|
|
872
|
+
resolveNext = null;
|
|
873
|
+
ended = false;
|
|
874
|
+
highWaterWarned = false;
|
|
875
|
+
push(evt) {
|
|
876
|
+
this.buffer.push(evt);
|
|
877
|
+
if (this.buffer.length > QUEUE_HIGH_WATER_MARK && !this.highWaterWarned) {
|
|
878
|
+
this.highWaterWarned = true;
|
|
879
|
+
console.warn(
|
|
880
|
+
`print-arm: event backlog exceeded ${QUEUE_HIGH_WATER_MARK} buffered events \u2014 downstream consumer is not keeping up. The child's stdout is still being drained (no ENOBUFS), but memory will grow until the consumer catches up.`
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
const resolve = this.resolveNext;
|
|
884
|
+
this.resolveNext = null;
|
|
885
|
+
resolve?.();
|
|
886
|
+
}
|
|
887
|
+
/** Signal that no further events will be pushed. */
|
|
888
|
+
end() {
|
|
889
|
+
this.ended = true;
|
|
890
|
+
const resolve = this.resolveNext;
|
|
891
|
+
this.resolveNext = null;
|
|
892
|
+
resolve?.();
|
|
893
|
+
}
|
|
894
|
+
async *[Symbol.asyncIterator]() {
|
|
895
|
+
for (; ; ) {
|
|
896
|
+
const evt = this.buffer.shift();
|
|
897
|
+
if (evt !== void 0) {
|
|
898
|
+
yield evt;
|
|
899
|
+
continue;
|
|
900
|
+
}
|
|
901
|
+
if (this.ended) return;
|
|
902
|
+
await new Promise((resolve) => {
|
|
903
|
+
this.resolveNext = resolve;
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
};
|
|
797
908
|
function mapMastraFinishReason(raw) {
|
|
798
909
|
switch (raw) {
|
|
799
910
|
case "complete":
|
|
@@ -847,9 +958,11 @@ var RuntimeConfigError = class extends Error {
|
|
|
847
958
|
}
|
|
848
959
|
};
|
|
849
960
|
function composeSpawn(handle, config) {
|
|
850
|
-
|
|
961
|
+
if (!config) return { binArgs: [...handle.bin_args ?? []], env: {}, envUnset: [] };
|
|
962
|
+
const prepend = [];
|
|
963
|
+
const append = [];
|
|
851
964
|
const env = {};
|
|
852
|
-
|
|
965
|
+
const envUnset = [];
|
|
853
966
|
if (config.mode !== void 0) {
|
|
854
967
|
const mode = (handle.modes ?? []).find((m) => m.id === config.mode);
|
|
855
968
|
if (!mode) {
|
|
@@ -860,8 +973,12 @@ function composeSpawn(handle, config) {
|
|
|
860
973
|
`Mode '${config.mode}' is not declared by manifest '${handle.id}'. Known modes: ${known}`
|
|
861
974
|
);
|
|
862
975
|
}
|
|
863
|
-
if (mode.
|
|
864
|
-
|
|
976
|
+
if ((mode.apply ?? "bin_args") === "bin_args") {
|
|
977
|
+
if (mode.bin_args_prepend) prepend.push(...mode.bin_args_prepend);
|
|
978
|
+
if (mode.bin_args_append) append.push(...mode.bin_args_append);
|
|
979
|
+
if (mode.env) Object.assign(env, mode.env);
|
|
980
|
+
if (mode.env_unset) envUnset.push(...mode.env_unset);
|
|
981
|
+
}
|
|
865
982
|
}
|
|
866
983
|
if (config.options && Object.keys(config.options).length > 0) {
|
|
867
984
|
const declared = handle.options ?? [];
|
|
@@ -881,8 +998,23 @@ function composeSpawn(handle, config) {
|
|
|
881
998
|
const value = config.options[option.id];
|
|
882
999
|
validateOptionValue(option, value);
|
|
883
1000
|
const patch = renderOptionPatch(option, value);
|
|
884
|
-
|
|
1001
|
+
prepend.push(...patch.prepend);
|
|
1002
|
+
append.push(...patch.append);
|
|
885
1003
|
Object.assign(env, patch.env);
|
|
1004
|
+
if (patch.envUnset.length) envUnset.push(...patch.envUnset);
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
const requestedModel = config.options?.model;
|
|
1008
|
+
if (typeof requestedModel === "string" && handle.models?.deny?.length) {
|
|
1009
|
+
const denyHit = handle.models.deny.find(
|
|
1010
|
+
(pattern) => matchesModelPattern(pattern, requestedModel)
|
|
1011
|
+
);
|
|
1012
|
+
if (denyHit) {
|
|
1013
|
+
throw new RuntimeConfigError(
|
|
1014
|
+
"model_denied",
|
|
1015
|
+
"config.options.model",
|
|
1016
|
+
`Model '${requestedModel}' is denied by manifest '${handle.id}' (matches deny pattern '${denyHit}'). This adapter deliberately does not route to that provider \u2014 use a permitted model or a different adapter.`
|
|
1017
|
+
);
|
|
886
1018
|
}
|
|
887
1019
|
}
|
|
888
1020
|
if (config.continuation !== void 0 && handle.continuation) {
|
|
@@ -894,12 +1026,21 @@ function composeSpawn(handle, config) {
|
|
|
894
1026
|
);
|
|
895
1027
|
}
|
|
896
1028
|
}
|
|
897
|
-
return {
|
|
1029
|
+
return {
|
|
1030
|
+
binArgs: [...prepend, ...handle.bin_args ?? [], ...append],
|
|
1031
|
+
env,
|
|
1032
|
+
envUnset
|
|
1033
|
+
};
|
|
898
1034
|
}
|
|
899
1035
|
function resolveContinuationStrategy(handle, config) {
|
|
900
1036
|
if (config?.continuation) return config.continuation;
|
|
901
1037
|
return handle.continuation?.default ?? "none";
|
|
902
1038
|
}
|
|
1039
|
+
function matchesModelPattern(pattern, modelId) {
|
|
1040
|
+
const p = pattern.toLowerCase();
|
|
1041
|
+
const m = modelId.toLowerCase();
|
|
1042
|
+
return p.endsWith("*") ? m.startsWith(p.slice(0, -1)) : m === p;
|
|
1043
|
+
}
|
|
903
1044
|
function validateOptionValue(option, value) {
|
|
904
1045
|
const path = `config.options.${option.id}`;
|
|
905
1046
|
switch (option.type) {
|
|
@@ -965,17 +1106,23 @@ function validateOptionValue(option, value) {
|
|
|
965
1106
|
function renderOptionPatch(option, value) {
|
|
966
1107
|
const stringValue = String(value);
|
|
967
1108
|
if (option.type === "boolean") {
|
|
968
|
-
if (value !== true) return {
|
|
1109
|
+
if (value !== true) return { prepend: [], append: [], env: {}, envUnset: [] };
|
|
969
1110
|
return {
|
|
970
|
-
|
|
971
|
-
|
|
1111
|
+
prepend: [],
|
|
1112
|
+
append: option.bin_args_append_when_true ? [...option.bin_args_append_when_true] : [],
|
|
1113
|
+
env: option.env ? interpolateEnv(option.env, stringValue) : {},
|
|
1114
|
+
envUnset: option.env_unset ? [...option.env_unset] : []
|
|
972
1115
|
};
|
|
973
1116
|
}
|
|
974
1117
|
return {
|
|
975
|
-
|
|
1118
|
+
prepend: option.bin_args_prepend ? option.bin_args_prepend.map(
|
|
1119
|
+
(token) => token.replace(/\{value\}/g, stringValue)
|
|
1120
|
+
) : [],
|
|
1121
|
+
append: option.bin_args_template ? option.bin_args_template.map(
|
|
976
1122
|
(token) => token.replace(/\{value\}/g, stringValue)
|
|
977
1123
|
) : [],
|
|
978
|
-
env: option.env ? interpolateEnv(option.env, stringValue) : {}
|
|
1124
|
+
env: option.env ? interpolateEnv(option.env, stringValue) : {},
|
|
1125
|
+
envUnset: option.env_unset ? [...option.env_unset] : []
|
|
979
1126
|
};
|
|
980
1127
|
}
|
|
981
1128
|
function interpolateEnv(env, value) {
|
|
@@ -1032,9 +1179,10 @@ function createAgentCliRuntime(definition) {
|
|
|
1032
1179
|
const composed = composeSpawn(definition, opts?.config);
|
|
1033
1180
|
const env = {
|
|
1034
1181
|
...filterStringEnv(process.env),
|
|
1035
|
-
...composed.env
|
|
1036
|
-
...opts?.env ?? {}
|
|
1182
|
+
...composed.env
|
|
1037
1183
|
};
|
|
1184
|
+
for (const k of composed.envUnset) delete env[k];
|
|
1185
|
+
Object.assign(env, opts?.env ?? {});
|
|
1038
1186
|
const permissionMode = resolveClaudeCodePermissionMode(
|
|
1039
1187
|
definition,
|
|
1040
1188
|
opts?.config?.mode
|
|
@@ -1091,6 +1239,9 @@ function createAgentCliRuntime(definition) {
|
|
|
1091
1239
|
const optEffort = opts?.config?.options?.effort;
|
|
1092
1240
|
const modelApply = definition.models?.apply ?? "config";
|
|
1093
1241
|
const configModel = optModel && modelApply === "config" ? String(optModel) : void 0;
|
|
1242
|
+
const requestedModeId = opts?.config?.mode;
|
|
1243
|
+
const requestedModeDecl = requestedModeId ? (definition.modes ?? []).find((m) => m.id === requestedModeId) : void 0;
|
|
1244
|
+
const configMode = requestedModeDecl?.apply === "config" ? requestedModeId : void 0;
|
|
1094
1245
|
const turnIdleTimeoutMs = opts?.turnIdleTimeoutMs ?? definition.session?.turn_idle_timeout_ms;
|
|
1095
1246
|
await arm.connect({
|
|
1096
1247
|
cwd,
|
|
@@ -1100,6 +1251,7 @@ function createAgentCliRuntime(definition) {
|
|
|
1100
1251
|
...opts?.mcpServers ? { mcpServers: opts.mcpServers } : {},
|
|
1101
1252
|
...configModel ? { model: configModel } : {},
|
|
1102
1253
|
...optEffort ? { effort: String(optEffort) } : {},
|
|
1254
|
+
...configMode ? { mode: configMode } : {},
|
|
1103
1255
|
...opts?.onActivity ? { onActivity: opts.onActivity } : {},
|
|
1104
1256
|
...turnIdleTimeoutMs !== void 0 ? { turnIdleTimeoutMs } : {}
|
|
1105
1257
|
});
|
|
@@ -1204,5 +1356,5 @@ function filterStringEnv(env) {
|
|
|
1204
1356
|
}
|
|
1205
1357
|
|
|
1206
1358
|
export { RuntimeConfigError, agentCliFrontmatterSchema, autoAllowPermissionHandler, composeSpawn, createAcpProtocolArm, createAgentCliRuntime, createMastraMapperState, createPrintSession, createProprietaryProtocolArm, defineAgentCli, mapMastraEvent, planModePermissionHandler, resolveContinuationStrategy, runtimeConfigSchema, toFileBasedMcpServers };
|
|
1207
|
-
//# sourceMappingURL=chunk-
|
|
1208
|
-
//# sourceMappingURL=chunk-
|
|
1359
|
+
//# sourceMappingURL=chunk-L6BRNMVP.mjs.map
|
|
1360
|
+
//# sourceMappingURL=chunk-L6BRNMVP.mjs.map
|