agent-devkit 0.3.5 → 0.5.6

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/main.js CHANGED
@@ -8,7 +8,7 @@ import React from "react";
8
8
  // package.json
9
9
  var package_default = {
10
10
  name: "agent-devkit",
11
- version: "0.3.5",
11
+ version: "0.5.6",
12
12
  description: "Agent DevKit CLI and TUI runtime for specialist AI agents, capabilities and provider-aware workflows.",
13
13
  license: "MIT",
14
14
  type: "module",
@@ -3385,6 +3385,80 @@ function createEnvironmentSurface() {
3385
3385
  // src/app/cli/toolRuntime.ts
3386
3386
  import { homedir as homedir11 } from "os";
3387
3387
 
3388
+ // src/infra/helpers/tool_schema_summary.ts
3389
+ var MAX_VARIANTS = 12;
3390
+ var MAX_PROPS = 10;
3391
+ var MAX_ENUM = 6;
3392
+ function asRecord(value) {
3393
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
3394
+ }
3395
+ function propHint(name, schema, required) {
3396
+ const suffix = required ? "" : "?";
3397
+ const enumValues = Array.isArray(schema?.enum) ? schema?.enum : void 0;
3398
+ if (enumValues !== void 0 && enumValues.length > 0) {
3399
+ const shown = enumValues.slice(0, MAX_ENUM).map(String).join("|");
3400
+ const more = enumValues.length > MAX_ENUM ? "|..." : "";
3401
+ return `${name}[${shown}${more}]${suffix}`;
3402
+ }
3403
+ return `${name}${suffix}`;
3404
+ }
3405
+ function detectDiscriminator(variants) {
3406
+ const first = asRecord(variants[0]?.properties);
3407
+ if (first === void 0) {
3408
+ return void 0;
3409
+ }
3410
+ for (const name of Object.keys(first)) {
3411
+ const isDiscriminator = variants.every((variant) => {
3412
+ const property = asRecord(asRecord(variant.properties)?.[name]);
3413
+ return property !== void 0 && (typeof property.const === "string" || Array.isArray(property.enum));
3414
+ });
3415
+ if (isDiscriminator) {
3416
+ return name;
3417
+ }
3418
+ }
3419
+ return void 0;
3420
+ }
3421
+ function variantSummary(variant, discriminator) {
3422
+ const props = asRecord(variant.properties);
3423
+ if (props === void 0) {
3424
+ return void 0;
3425
+ }
3426
+ const required = new Set(Array.isArray(variant.required) ? variant.required : []);
3427
+ const discriminatorSchema = asRecord(props[discriminator]);
3428
+ const label = typeof discriminatorSchema?.const === "string" ? discriminatorSchema.const : Array.isArray(discriminatorSchema?.enum) ? String((discriminatorSchema?.enum)[0]) : void 0;
3429
+ if (label === void 0) {
3430
+ return void 0;
3431
+ }
3432
+ const params = Object.keys(props).filter((name) => name !== discriminator).slice(0, MAX_PROPS).map((name) => propHint(name, asRecord(props[name]), required.has(name)));
3433
+ const paramText = params.length > 0 ? `(${params.join(", ")})` : "";
3434
+ return `${label}${paramText}`;
3435
+ }
3436
+ function summarizeToolSchema(schema) {
3437
+ const union = Array.isArray(schema.oneOf) ? schema.oneOf : Array.isArray(schema.anyOf) ? schema.anyOf : void 0;
3438
+ if (union !== void 0) {
3439
+ const variants = union.map(asRecord).filter((variant) => variant !== void 0);
3440
+ const discriminator = detectDiscriminator(variants) ?? "action";
3441
+ const summaries = variants.slice(0, MAX_VARIANTS).map((variant) => variantSummary(variant, discriminator)).filter((summary) => summary !== void 0);
3442
+ if (summaries.length === 0) {
3443
+ return "";
3444
+ }
3445
+ const more2 = variants.length > MAX_VARIANTS ? " | ..." : "";
3446
+ return `${discriminator} = ${summaries.join(" | ")}${more2}`;
3447
+ }
3448
+ const props = asRecord(schema.properties);
3449
+ if (props === void 0) {
3450
+ return "";
3451
+ }
3452
+ const required = new Set(Array.isArray(schema.required) ? schema.required : []);
3453
+ const names = Object.keys(props);
3454
+ const fields = names.slice(0, MAX_PROPS).map((name) => propHint(name, asRecord(props[name]), required.has(name)));
3455
+ if (fields.length === 0) {
3456
+ return "";
3457
+ }
3458
+ const more = names.length > MAX_PROPS ? ", ..." : "";
3459
+ return `fields: ${fields.join(", ")}${more}`;
3460
+ }
3461
+
3388
3462
  // src/infra/models/model_store.ts
3389
3463
  import { createHash } from "crypto";
3390
3464
  import { once } from "events";
@@ -3724,11 +3798,14 @@ function systemPromptFrom(prompt) {
3724
3798
  );
3725
3799
  }
3726
3800
  if (prompt.tools.length > 0) {
3727
- lines.push(
3728
- "",
3729
- "Available tools:",
3730
- ...prompt.tools.map((tool) => `- ${tool.id} (${tool.risk}): ${tool.description}`)
3731
- );
3801
+ lines.push("", "Available tools:");
3802
+ for (const tool of prompt.tools) {
3803
+ lines.push(`- ${tool.id} (${tool.risk}): ${tool.description}`);
3804
+ const schema = tool.inputSchema === void 0 ? "" : summarizeToolSchema(tool.inputSchema);
3805
+ if (schema.length > 0) {
3806
+ lines.push(` input: ${schema}`);
3807
+ }
3808
+ }
3732
3809
  }
3733
3810
  lines.push(
3734
3811
  "",
@@ -3743,7 +3820,7 @@ function systemPromptFrom(prompt) {
3743
3820
  );
3744
3821
  }
3745
3822
  lines.push(`Reply in ${prompt.output.language}.`);
3746
- const history = prompt.messages.filter((message) => message.role === "user" || message.role === "assistant").slice(0, -1).map((message) => `${message.role === "user" ? "User" : agent.name}: ${message.content}`);
3823
+ const history = prompt.messages.filter((message) => message.role === "user" || message.role === "assistant").slice(0, -1).map((message) => `${message.role}: ${message.content}`);
3747
3824
  if (history.length > 0) {
3748
3825
  lines.push("", "Conversation so far:", ...history);
3749
3826
  }
@@ -3878,7 +3955,9 @@ var LocalLlamaBrainProvider = class {
3878
3955
  return cached;
3879
3956
  }
3880
3957
  if (this.#llama === void 0) {
3881
- this.#llama = await llama.getLlama();
3958
+ this.#llama = await llama.getLlama({
3959
+ logLevel: llama.LlamaLogLevel?.error ?? llama.LlamaLogLevel?.fatal
3960
+ });
3882
3961
  }
3883
3962
  const model = await this.#llama.loadModel({ modelPath });
3884
3963
  this.#models.set(modelPath, model);
@@ -3888,7 +3967,7 @@ var LocalLlamaBrainProvider = class {
3888
3967
 
3889
3968
  // src/infra/brain/mock_provider.ts
3890
3969
  function reply(request) {
3891
- const text2 = `${request.prompt.agent.name}: Entendi. Vou responder no contexto da sess\xE3o atual: "${request.prompt.task.userMessage}".`;
3970
+ const text2 = `Entendi. Vou responder no contexto da sess\xE3o atual: "${request.prompt.task.userMessage}".`;
3892
3971
  const inputTokens = request.prompt.messages.map((message) => message.content.split(/\s+/g).filter(Boolean).length).reduce((total, count) => total + count, 0);
3893
3972
  const outputTokens = text2.split(/\s+/g).filter(Boolean).length;
3894
3973
  return {
@@ -3913,8 +3992,11 @@ var MockBrainProvider = class {
3913
3992
  onToken(response.text);
3914
3993
  return Result.ok(response);
3915
3994
  }
3916
- async generateStructured(request, _jsonSchema) {
3917
- const raw = JSON.stringify({ action: "final", reply: reply(request).text });
3995
+ async generateStructured(request, jsonSchema) {
3996
+ const properties = typeof jsonSchema.properties === "object" && jsonSchema.properties !== null && !Array.isArray(jsonSchema.properties) ? jsonSchema.properties : {};
3997
+ const isAgentRouteSchema = "action" in properties && "tool" in properties;
3998
+ const text2 = isAgentRouteSchema ? "Mock brain ativo. Instale ou configure um modelo local para executar roteamento agentic real." : reply(request).text;
3999
+ const raw = JSON.stringify({ action: "final", reply: text2 });
3918
4000
  return Result.ok({ json: JSON.parse(raw), raw });
3919
4001
  }
3920
4002
  };
@@ -5676,37 +5758,19 @@ var conversationChatCapabilityConfig = defineCapabilityConfig({
5676
5758
  kind: "brain-assisted",
5677
5759
  risk: "writes-global-state"
5678
5760
  });
5679
- function normalizeQuestion(value) {
5680
- return value.normalize("NFD").replaceAll(new RegExp("\\p{Diacritic}", "gu"), "").toLowerCase().replaceAll(/[^\p{Letter}\p{Number}\s]/gu, " ").replaceAll(/\s+/g, " ").trim();
5681
- }
5682
- function isSelfDescriptionQuestion(message) {
5683
- const normalized = normalizeQuestion(message);
5684
- return normalized === "o que voce pode fazer" || normalized === "o que voce faz" || normalized === "quais sao suas capacidades" || normalized === "quais suas capacidades" || normalized === "what can you do" || normalized === "what do you do";
5761
+ function stripLeadingAgentPrefixes(text2, agentName) {
5762
+ const escaped = agentName.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
5763
+ const prefixPattern = new RegExp(`^(?:\\s*${escaped}\\s*:\\s*)+`, "iu");
5764
+ return text2.replace(prefixPattern, "").trim();
5685
5765
  }
5686
- function countPromptTokens(request) {
5687
- return request.prompt.messages.map((message) => message.content.split(/\s+/g).filter(Boolean).length).reduce((total, count) => total + count, 0);
5688
- }
5689
- function selfDescriptionResponse(request) {
5690
- if (!isSelfDescriptionQuestion(request.prompt.task.userMessage)) {
5691
- return void 0;
5692
- }
5693
- const { agent } = request.prompt;
5694
- const traits = agent.traits.length === 0 ? "sem tracos extras configurados" : agent.traits.join(", ");
5695
- const text2 = `${agent.name}: Eu posso conversar com voce mantendo o contexto da sessao, ajudar a raciocinar, organizar ideias, analisar informacoes e responder no meu estilo configurado. Minha postura e ${agent.behavior}, meu tom e ${agent.tone}, meu nivel de detalhe e ${agent.detailLevel}, e meus tracos atuais sao: ${traits}.`;
5696
- const inputTokens = countPromptTokens(request);
5766
+ function responseWithText(response, text2) {
5697
5767
  const outputTokens = text2.split(/\s+/g).filter(Boolean).length;
5698
- return {
5699
- finishReason: "stop",
5700
- model: "self-description",
5701
- provider: "system",
5702
- schema: "agent-devkit.brain-response/v1",
5703
- text: text2,
5704
- usage: {
5705
- inputTokens,
5706
- outputTokens,
5707
- totalTokens: inputTokens + outputTokens
5708
- }
5768
+ const usage = response.usage === void 0 ? void 0 : {
5769
+ ...response.usage,
5770
+ outputTokens,
5771
+ totalTokens: response.usage.inputTokens === void 0 ? response.usage.totalTokens : response.usage.inputTokens + outputTokens
5709
5772
  };
5773
+ return { ...response, text: text2, usage };
5710
5774
  }
5711
5775
  var ConversationChatService = class extends BaseCapabilityService {
5712
5776
  inputSchema = ConversationChatOptionsSchema;
@@ -5751,32 +5815,32 @@ var ConversationChatService = class extends BaseCapabilityService {
5751
5815
  return Result.fail(prepared.unwrapError());
5752
5816
  }
5753
5817
  const request = {
5754
- options: parsed.data.brain ?? { provider: "local" },
5818
+ options: { provider: "local", ...parsed.data.brain, role: "chat" },
5755
5819
  prompt: prepared.unwrap().prompt,
5756
5820
  schema: "agent-devkit.brain-request/v1"
5757
5821
  };
5758
- const selfDescription = selfDescriptionResponse(request);
5759
- const brain = selfDescription === void 0 ? onToken !== void 0 && this.#brainProvider.generateStream !== void 0 ? await this.#brainProvider.generateStream(request, onToken) : await this.#brainProvider.generate(request) : Result.ok(selfDescription);
5760
- if (selfDescription !== void 0) {
5761
- onToken?.(selfDescription.text);
5762
- }
5822
+ const brain = onToken !== void 0 && this.#brainProvider.generateStream !== void 0 ? await this.#brainProvider.generateStream(request, onToken) : await this.#brainProvider.generate(request);
5763
5823
  if (brain.isErr()) {
5764
5824
  return Result.fail(brain.unwrapError());
5765
5825
  }
5826
+ const normalizedBrain = responseWithText(
5827
+ brain.unwrap(),
5828
+ stripLeadingAgentPrefixes(brain.unwrap().text, prepared.unwrap().prompt.agent.name)
5829
+ );
5766
5830
  const messages = await this.#repository.appendAssistantMessage(
5767
5831
  prepared.unwrap().sessionId,
5768
- brain.unwrap().text
5832
+ normalizedBrain.text
5769
5833
  );
5770
5834
  if (messages.isErr()) {
5771
5835
  return Result.fail(messages.unwrapError());
5772
5836
  }
5773
5837
  const result = this.outputSchema.safeParse({
5774
5838
  action: "send",
5775
- brain: brain.unwrap(),
5839
+ brain: normalizedBrain,
5776
5840
  messages: messages.unwrap(),
5777
5841
  projectId: prepared.unwrap().projectId,
5778
5842
  prompt: prepared.unwrap().prompt,
5779
- reply: brain.unwrap().text,
5843
+ reply: normalizedBrain.text,
5780
5844
  sessionId: prepared.unwrap().sessionId
5781
5845
  });
5782
5846
  return result.success ? Result.ok(result.data) : Result.fail(ErrorCodes.InvalidInput);
@@ -8140,6 +8204,37 @@ function registerLogsCommand(program2, options) {
8140
8204
  );
8141
8205
  }
8142
8206
 
8207
+ // src/modules/module_knowledge_catalog.ts
8208
+ function createModuleSurfaceKnowledge() {
8209
+ let cache;
8210
+ return {
8211
+ async all() {
8212
+ if (cache !== void 0) {
8213
+ return cache;
8214
+ }
8215
+ const modules = [];
8216
+ for (const definition of agentModuleDefinitions) {
8217
+ const surface = definition.surface();
8218
+ const [knowledge, skill, loop] = await Promise.all([
8219
+ surface.knowledge(),
8220
+ surface.skill(),
8221
+ surface.loop()
8222
+ ]);
8223
+ modules.push({
8224
+ facts: knowledge.isOk() ? knowledge.unwrap().facts : [],
8225
+ forbiddenActions: loop.isOk() ? loop.unwrap().forbiddenActions : [],
8226
+ moduleId: definition.id,
8227
+ summary: knowledge.isOk() ? knowledge.unwrap().summary : "",
8228
+ whenNotToUse: skill.isOk() ? skill.unwrap().whenNotToUse : [],
8229
+ whenToUse: skill.isOk() ? skill.unwrap().whenToUse : []
8230
+ });
8231
+ }
8232
+ cache = modules;
8233
+ return modules;
8234
+ }
8235
+ };
8236
+ }
8237
+
8143
8238
  // src/app/mcp/mcp_http_transport.ts
8144
8239
  import { createServer } from "http";
8145
8240
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
@@ -8150,54 +8245,78 @@ import { join as join16 } from "path";
8150
8245
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
8151
8246
  import {
8152
8247
  CallToolRequestSchema,
8153
- ListToolsRequestSchema
8248
+ ListResourcesRequestSchema,
8249
+ ListToolsRequestSchema,
8250
+ ReadResourceRequestSchema
8154
8251
  } from "@modelcontextprotocol/sdk/types.js";
8155
8252
 
8156
8253
  // src/agent/agent.brain.ts
8157
8254
  import { z as z23 } from "zod";
8158
- var AgentDecisionSchema = z23.discriminatedUnion("action", [
8159
- z23.object({ action: z23.literal("tool"), input: z23.unknown(), tool: z23.string().min(1) }),
8255
+ var AgentRouteSchema = z23.discriminatedUnion("action", [
8256
+ z23.object({ action: z23.literal("tool"), tool: z23.string().min(1) }),
8160
8257
  z23.object({ action: z23.literal("final"), reply: z23.string() })
8161
8258
  ]);
8162
- var agentDecisionJsonSchema = {
8259
+ var agentRouteJsonSchema = {
8163
8260
  type: "object",
8164
8261
  properties: {
8165
8262
  action: { type: "string", enum: ["tool", "final"] },
8166
- input: { type: "object" },
8167
8263
  reply: { type: "string" },
8168
8264
  tool: { type: "string" }
8169
8265
  },
8170
8266
  required: ["action"]
8171
8267
  };
8268
+ var agentPersona = {
8269
+ behavior: "balanced",
8270
+ characterId: "agent",
8271
+ detailLevel: "concise",
8272
+ name: "Agent",
8273
+ tone: "direct",
8274
+ traits: []
8275
+ };
8276
+ var identityKnowledge = {
8277
+ content: "You are the Agent DevKit orchestration runtime. Choose tools only when they directly help complete the user's task.",
8278
+ id: "agent.runtime.identity"
8279
+ };
8172
8280
  function maxToolCallsFor(tools) {
8173
8281
  return Math.max(1, tools.length);
8174
8282
  }
8283
+ function moduleGuidance(knowledge) {
8284
+ const entries = [];
8285
+ for (const module of knowledge) {
8286
+ const parts = [];
8287
+ if (module.summary.length > 0) {
8288
+ parts.push(module.summary);
8289
+ }
8290
+ if (module.whenToUse.length > 0) {
8291
+ parts.push(`Use when: ${module.whenToUse.join(" ")}`);
8292
+ }
8293
+ if (module.whenNotToUse.length > 0) {
8294
+ parts.push(`Avoid when: ${module.whenNotToUse.join(" ")}`);
8295
+ }
8296
+ if (module.forbiddenActions.length > 0) {
8297
+ parts.push(`Never: ${module.forbiddenActions.join(" ")}`);
8298
+ }
8299
+ if (parts.length === 0) {
8300
+ continue;
8301
+ }
8302
+ entries.push({
8303
+ content: `${module.moduleId} \u2014 ${parts.join(" ")}`,
8304
+ id: `module.${module.moduleId}`
8305
+ });
8306
+ }
8307
+ return entries;
8308
+ }
8175
8309
  function buildToolDecisionPrompt(input) {
8176
- const toolList = input.tools.map((tool) => `- ${tool.id} (${tool.risk}): ${tool.description}`).join("\n");
8177
8310
  const instruction = [
8178
8311
  `Tarefa do usu\xE1rio: ${input.task}`,
8179
8312
  "",
8180
- "Ferramentas dispon\xEDveis:",
8181
- toolList,
8182
- "",
8183
- 'Responda SOMENTE com JSON. Para usar uma ferramenta: {"action":"tool","tool":"<id>","input":{...}}. Para responder ao usu\xE1rio: {"action":"final","reply":"<texto>"}. Uma a\xE7\xE3o por vez.'
8313
+ "Escolha UMA ferramenta da lista dispon\xEDvel para avan\xE7ar na tarefa, ou responda ao usu\xE1rio se j\xE1 puder concluir.",
8314
+ 'Responda SOMENTE com JSON. Para usar uma ferramenta: {"action":"tool","tool":"<id>"}. Para responder: {"action":"final","reply":"<texto>"}. Uma a\xE7\xE3o por vez. Os argumentos da ferramenta s\xE3o definidos no passo seguinte.'
8184
8315
  ].join("\n");
8185
8316
  return AgentPromptSchema.parse({
8186
- agent: {
8187
- behavior: "balanced",
8188
- characterId: "agent",
8189
- detailLevel: "concise",
8190
- name: "Agent",
8191
- tone: "direct",
8192
- traits: []
8193
- },
8317
+ agent: input.agent ?? agentPersona,
8194
8318
  context: {
8195
- knowledge: [
8196
- {
8197
- content: "You are the Agent DevKit orchestration runtime. Choose tools only when they directly help complete the user's task.",
8198
- id: "agent.runtime.identity"
8199
- }
8200
- ]
8319
+ knowledge: [identityKnowledge, ...moduleGuidance(input.knowledge ?? [])]
8201
8320
  },
8202
8321
  locale: "pt-BR",
8203
8322
  messages: input.transcript,
@@ -8217,6 +8336,34 @@ function buildToolDecisionPrompt(input) {
8217
8336
  }))
8218
8337
  });
8219
8338
  }
8339
+ function buildToolInputPrompt(input) {
8340
+ const schema = summarizeToolSchema(input.tool.inputSchema);
8341
+ const instruction = [
8342
+ `Tarefa do usu\xE1rio: ${input.task}`,
8343
+ "",
8344
+ `Gere APENAS o objeto JSON de entrada para a ferramenta ${input.tool.id}.`,
8345
+ schema.length > 0 ? `Formato esperado: ${schema}` : "",
8346
+ "Responda somente com o JSON do input, sem texto extra."
8347
+ ].filter((line) => line.length > 0).join("\n");
8348
+ return AgentPromptSchema.parse({
8349
+ agent: input.agent ?? agentPersona,
8350
+ context: { knowledge: [identityKnowledge] },
8351
+ locale: "pt-BR",
8352
+ messages: input.transcript,
8353
+ output: { format: "json", language: "pt-BR" },
8354
+ policies: { allowToolCalls: true, approvalRequired: false, maxToolCalls: 1 },
8355
+ schema: "agent-devkit.prompt/v1",
8356
+ task: { userMessage: instruction },
8357
+ tools: [
8358
+ {
8359
+ description: input.tool.description,
8360
+ id: input.tool.id,
8361
+ inputSchema: input.tool.inputSchema,
8362
+ risk: input.tool.risk
8363
+ }
8364
+ ]
8365
+ });
8366
+ }
8220
8367
 
8221
8368
  // src/agent/agent.policy.ts
8222
8369
  function isToolApproved(tool, input) {
@@ -8239,10 +8386,14 @@ function observationSummary(result) {
8239
8386
  return `${result.status}${result.error === void 0 ? "" : `: ${result.error.message}`}`;
8240
8387
  }
8241
8388
  var AgentToolLoop = class {
8389
+ #agent;
8242
8390
  #brain;
8391
+ #knowledge;
8243
8392
  #tools;
8244
8393
  constructor(options) {
8394
+ this.#agent = options.agent;
8245
8395
  this.#brain = options.brainProvider;
8396
+ this.#knowledge = options.knowledge;
8246
8397
  this.#tools = options.toolRuntime;
8247
8398
  }
8248
8399
  async run(input) {
@@ -8257,35 +8408,50 @@ var AgentToolLoop = class {
8257
8408
  role: message.role
8258
8409
  }));
8259
8410
  const tools = this.#tools.listTools();
8411
+ const knowledge = await this.#knowledgeForTools(tools.map((tool) => tool.moduleId));
8260
8412
  for (let step = 0; step < maxSteps; step += 1) {
8261
- const prompt = buildToolDecisionPrompt({
8413
+ const routePrompt = buildToolDecisionPrompt({
8414
+ agent: input.agent ?? this.#agent,
8415
+ knowledge,
8262
8416
  task: input.task,
8263
8417
  tools,
8264
8418
  transcript
8265
8419
  });
8266
- const request = {
8267
- options: { provider: "local", role: "agent" },
8268
- prompt,
8269
- schema: "agent-devkit.brain-request/v1"
8270
- };
8271
- const structured = await generateStructured(request, agentDecisionJsonSchema);
8272
- if (structured.isErr()) {
8273
- return Result.fail(structured.unwrapError());
8420
+ const routed = await generateStructured(
8421
+ {
8422
+ options: { provider: "local", role: "agent" },
8423
+ prompt: routePrompt,
8424
+ schema: "agent-devkit.brain-request/v1"
8425
+ },
8426
+ agentRouteJsonSchema
8427
+ );
8428
+ if (routed.isErr()) {
8429
+ return Result.fail(routed.unwrapError());
8274
8430
  }
8275
- const decision = AgentDecisionSchema.safeParse(structured.unwrap().json);
8276
- if (!decision.success) {
8277
- return Result.ok({ mode: "task", reply: structured.unwrap().raw.trim(), steps });
8431
+ const route = AgentRouteSchema.safeParse(routed.unwrap().json);
8432
+ if (!route.success) {
8433
+ return Result.fail(ErrorCodes.InvalidInput);
8278
8434
  }
8279
- if (decision.data.action === "final") {
8280
- input.onEvent?.({ reply: decision.data.reply, type: "final" });
8281
- return Result.ok({ mode: "task", reply: decision.data.reply, steps });
8435
+ if (route.data.action === "final") {
8436
+ input.onEvent?.({ reply: route.data.reply, type: "final" });
8437
+ return Result.ok({ mode: "task", reply: route.data.reply, steps });
8282
8438
  }
8283
- const tool = decision.data.tool;
8439
+ const tool = route.data.tool;
8284
8440
  input.onEvent?.({ tool, type: "tool" });
8441
+ const toolInput = await this.#resolveToolInput(
8442
+ generateStructured,
8443
+ tool,
8444
+ input.task,
8445
+ transcript,
8446
+ input.agent ?? this.#agent
8447
+ );
8448
+ if (toolInput.isErr()) {
8449
+ return Result.fail(toolInput.unwrapError());
8450
+ }
8285
8451
  const execution = await this.#tools.execute({
8286
8452
  approved: isToolApproved(tool, input),
8287
8453
  capabilityId: tool,
8288
- input: decision.data.input,
8454
+ input: toolInput.unwrap(),
8289
8455
  interface: input.interface ?? "agent",
8290
8456
  requestedBy: "agent.run"
8291
8457
  });
@@ -8308,6 +8474,30 @@ var AgentToolLoop = class {
8308
8474
  steps
8309
8475
  });
8310
8476
  }
8477
+ async #knowledgeForTools(moduleIds) {
8478
+ if (this.#knowledge === void 0) {
8479
+ return [];
8480
+ }
8481
+ const present = new Set(moduleIds);
8482
+ const all = await this.#knowledge.all();
8483
+ return all.filter((module) => present.has(module.moduleId));
8484
+ }
8485
+ async #resolveToolInput(generateStructured, tool, task, transcript, agent) {
8486
+ const descriptor = this.#tools.getTool(tool);
8487
+ if (descriptor.isErr()) {
8488
+ return Result.fail(descriptor.unwrapError());
8489
+ }
8490
+ const request = {
8491
+ options: { provider: "local", role: "agent" },
8492
+ prompt: buildToolInputPrompt({ agent, task, tool: descriptor.unwrap(), transcript }),
8493
+ schema: "agent-devkit.brain-request/v1"
8494
+ };
8495
+ const produced = await generateStructured(request, descriptor.unwrap().inputSchema);
8496
+ if (produced.isErr()) {
8497
+ return Result.fail(produced.unwrapError());
8498
+ }
8499
+ return Result.ok(produced.unwrap().json ?? {});
8500
+ }
8311
8501
  };
8312
8502
 
8313
8503
  // src/agent/agent.runtime.ts
@@ -8334,12 +8524,16 @@ function chatInput(input, message) {
8334
8524
  };
8335
8525
  }
8336
8526
  var AgentRuntime = class {
8527
+ #agent;
8337
8528
  #conversation;
8338
8529
  #toolLoop;
8339
8530
  constructor(options) {
8531
+ this.#agent = options.agent;
8340
8532
  this.#conversation = options.conversation;
8341
8533
  this.#toolLoop = new AgentToolLoop({
8534
+ agent: options.agent,
8342
8535
  brainProvider: options.brainProvider,
8536
+ knowledge: options.knowledge,
8343
8537
  toolRuntime: options.toolRuntime
8344
8538
  });
8345
8539
  }
@@ -8352,7 +8546,7 @@ var AgentRuntime = class {
8352
8546
  if (mode === "chat") {
8353
8547
  return this.#runChat(input, message);
8354
8548
  }
8355
- return this.#toolLoop.run({ ...input, task: message });
8549
+ return this.#toolLoop.run({ ...input, agent: input.agent ?? this.#agent, task: message });
8356
8550
  }
8357
8551
  async #runChat(input, message) {
8358
8552
  if (this.#conversation === void 0) {
@@ -8480,6 +8674,11 @@ var agentTaskTool = {
8480
8674
  annotations: { openWorldHint: true },
8481
8675
  _meta: { "agent-devkit/kind": "agent-delegation" }
8482
8676
  };
8677
+ var baseInstructions = "Agent DevKit exposes local capabilities as MCP tools, plus an `agent.task` delegation tool. Prefer `agent.task` for bounded, multi-step or routine local tasks to offload orchestration and reduce token usage; use the individual capability tools directly when you need step-by-step control or precise intermediate results. Risky tools require explicit approval through _agent.approved. For agent.task, approval must be scoped with approvedTools.";
8678
+ var surfaceResourceInstructions = " Per-module guidance (purpose, when to use, guardrails) is available as MCP resources under agent-devkit://surface/<moduleId>; read them to route between agent.task and direct capability tools.";
8679
+ function surfaceResourceUri(moduleId) {
8680
+ return `agent-devkit://surface/${moduleId}`;
8681
+ }
8483
8682
  function mcpToolFromRuntimeTool(tool) {
8484
8683
  const mcpTool = {
8485
8684
  name: tool.id,
@@ -8502,21 +8701,37 @@ function mcpToolFromRuntimeTool(tool) {
8502
8701
  }
8503
8702
  return mcpTool;
8504
8703
  }
8704
+ async function currentAgentPersona(personalization) {
8705
+ const profile = await personalization.loadProfile();
8706
+ if (profile.isErr()) {
8707
+ return void 0;
8708
+ }
8709
+ const character = profile.unwrap().currentCharacter;
8710
+ return {
8711
+ behavior: character.profile.behavior,
8712
+ characterId: character.id,
8713
+ detailLevel: character.profile.detailLevel,
8714
+ name: character.name ?? character.id,
8715
+ tone: character.profile.tone,
8716
+ traits: character.profile.traits
8717
+ };
8718
+ }
8505
8719
  function createAgentMcpServer(options) {
8720
+ const knowledge = options.knowledge;
8721
+ const personalization = new PersonalizationRepository();
8506
8722
  const server = new Server(
8507
8723
  {
8508
8724
  name: options.packageName,
8509
8725
  version: options.version
8510
8726
  },
8511
8727
  {
8512
- capabilities: {
8513
- tools: {}
8514
- },
8515
- instructions: "Agent DevKit exposes local capabilities as MCP tools, plus an `agent.task` delegation tool. Prefer `agent.task` for bounded, multi-step or routine local tasks to offload orchestration and reduce token usage; use the individual capability tools directly when you need step-by-step control or precise intermediate results. Risky tools require explicit approval through _agent.approved. For agent.task, approval must be scoped with approvedTools."
8728
+ capabilities: knowledge === void 0 ? { tools: {} } : { resources: {}, tools: {} },
8729
+ instructions: knowledge === void 0 ? baseInstructions : `${baseInstructions}${surfaceResourceInstructions}`
8516
8730
  }
8517
8731
  );
8518
8732
  const agent = new AgentRuntime({
8519
8733
  brainProvider: createBrainDockProvider({ stateDirectory: join16(homedir13(), ".agent-devkit") }),
8734
+ knowledge,
8520
8735
  toolRuntime: options.runtime
8521
8736
  });
8522
8737
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
@@ -8530,7 +8745,13 @@ function createAgentMcpServer(options) {
8530
8745
  if (task.length === 0) {
8531
8746
  return { content: [{ type: "text", text: "Missing 'task'." }], isError: true };
8532
8747
  }
8533
- const run = await agent.run({ approvedTools, interface: "mcp", mode: "task", task });
8748
+ const run = await agent.run({
8749
+ agent: await currentAgentPersona(personalization),
8750
+ approvedTools,
8751
+ interface: "mcp",
8752
+ mode: "task",
8753
+ task
8754
+ });
8534
8755
  if (run.isErr()) {
8535
8756
  return {
8536
8757
  content: [{ type: "text", text: `Agent run failed: ${run.unwrapError()}` }],
@@ -8564,6 +8785,37 @@ ${stepsText}` : payload.reply
8564
8785
  const tool = options.runtime.getTool(request.params.name);
8565
8786
  return runtimeResultToMcpContent(result, tool.isOk() && hasObjectOutputSchema(tool.unwrap()));
8566
8787
  });
8788
+ if (knowledge !== void 0) {
8789
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
8790
+ const modules = await knowledge.all();
8791
+ return {
8792
+ resources: modules.map((module) => ({
8793
+ description: module.summary,
8794
+ mimeType: "application/json",
8795
+ name: `${module.moduleId} surface`,
8796
+ uri: surfaceResourceUri(module.moduleId)
8797
+ }))
8798
+ };
8799
+ });
8800
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
8801
+ const modules = await knowledge.all();
8802
+ const module = modules.find(
8803
+ (entry) => surfaceResourceUri(entry.moduleId) === request.params.uri
8804
+ );
8805
+ if (module === void 0) {
8806
+ throw new Error(`Unknown resource: ${request.params.uri}`);
8807
+ }
8808
+ return {
8809
+ contents: [
8810
+ {
8811
+ mimeType: "application/json",
8812
+ text: JSON.stringify(module, null, 2),
8813
+ uri: request.params.uri
8814
+ }
8815
+ ]
8816
+ };
8817
+ });
8818
+ }
8567
8819
  return server;
8568
8820
  }
8569
8821
 
@@ -8661,6 +8913,7 @@ function runtime2(options) {
8661
8913
  }
8662
8914
  async function runStdio(options) {
8663
8915
  await startMcpStdioServer({
8916
+ knowledge: createModuleSurfaceKnowledge(),
8664
8917
  packageName: options.packageName,
8665
8918
  runtime: runtime2(options),
8666
8919
  version: options.currentVersion
@@ -8715,6 +8968,7 @@ function registerMcpCommand(program2, options) {
8715
8968
  const server = await startMcpHttpServer({
8716
8969
  allowedOrigins: commandOptions.origin,
8717
8970
  host: commandOptions.host,
8971
+ knowledge: createModuleSurfaceKnowledge(),
8718
8972
  packageName: options.packageName,
8719
8973
  port: parsePositiveInteger(commandOptions.port),
8720
8974
  runtime: runtime2(options),
@@ -9794,6 +10048,16 @@ function registerSecretsCommand(program2, options) {
9794
10048
  }
9795
10049
 
9796
10050
  // src/app/cli/commands/sessionsCommand.ts
10051
+ function stringOption(options, ...names) {
10052
+ const nested = typeof options.opts === "function" ? options.opts() : {};
10053
+ for (const name of names) {
10054
+ const value = options[name] ?? nested[name];
10055
+ if (typeof value === "string" && value.length > 0) {
10056
+ return value;
10057
+ }
10058
+ }
10059
+ return void 0;
10060
+ }
9797
10061
  function parseTags2(value) {
9798
10062
  const tags = value?.split(",").map((tag) => tag.trim()).filter((tag) => tag.length > 0);
9799
10063
  return tags === void 0 || tags.length === 0 ? void 0 : tags;
@@ -9826,14 +10090,14 @@ function registerSessionsCommand(program2, options) {
9826
10090
  await printSessionsResult(commandOptions, {
9827
10091
  action: "list",
9828
10092
  limit: parseNonNegativeInteger(commandOptions.limit),
9829
- projectId: commandOptions.project,
10093
+ projectId: stringOption(commandOptions, "project", "projectId"),
9830
10094
  query: commandOptions.query,
9831
10095
  status: commandOptions.status
9832
10096
  });
9833
10097
  }
9834
10098
  )
9835
10099
  );
9836
- const createCommand = sessionsCommand.command("create").description("create a context session").option("--json", "print session result as JSON").option("--origin <origin>", "cli, tui, mcp or agent", "cli").option("--project <projectId>", "project id").option("--tags <tags>", "comma-separated tags").option("--title <title>", "session title");
10100
+ const createCommand = sessionsCommand.command("create").description("create a context session").option("--json", "print session result as JSON").option("--origin <origin>", "cli, tui, mcp or agent", "cli").option("--tags <tags>", "comma-separated tags").option("--title <title>", "session title");
9837
10101
  createCommand.action(
9838
10102
  options.usageLogging.track(
9839
10103
  { area: "user", command: "sessions.create", options: () => createCommand.opts() },
@@ -9841,7 +10105,7 @@ function registerSessionsCommand(program2, options) {
9841
10105
  await printSessionsResult(commandOptions, {
9842
10106
  action: "create",
9843
10107
  origin: commandOptions.origin ?? "cli",
9844
- projectId: commandOptions.project,
10108
+ projectId: stringOption(commandOptions, "project", "projectId") ?? stringOption(sessionsCommand.opts(), "project", "projectId"),
9845
10109
  tags: parseTags2(commandOptions.tags),
9846
10110
  title: commandOptions.title
9847
10111
  });
@@ -9877,7 +10141,7 @@ function registerSessionsCommand(program2, options) {
9877
10141
  }
9878
10142
  )
9879
10143
  );
9880
- const searchCommand = sessionsCommand.command("search").argument("<query>", "query").description("search context sessions").option("--json", "print session result as JSON").option("--limit <limit>", "maximum number of results").option("--project <projectId>", "project id");
10144
+ const searchCommand = sessionsCommand.command("search").argument("<query>", "query").description("search context sessions").option("--json", "print session result as JSON").option("--limit <limit>", "maximum number of results");
9881
10145
  searchCommand.action(
9882
10146
  options.usageLogging.track(
9883
10147
  { area: "user", command: "sessions.search", options: () => searchCommand.opts() },
@@ -9885,7 +10149,7 @@ function registerSessionsCommand(program2, options) {
9885
10149
  await printSessionsResult(commandOptions, {
9886
10150
  action: "search",
9887
10151
  limit: parseNonNegativeInteger(commandOptions.limit),
9888
- projectId: commandOptions.project,
10152
+ projectId: stringOption(commandOptions, "project", "projectId") ?? stringOption(sessionsCommand.opts(), "project", "projectId"),
9889
10153
  query
9890
10154
  });
9891
10155
  }
@@ -10157,10 +10421,7 @@ import { homedir as homedir22 } from "os";
10157
10421
 
10158
10422
  // src/modules/conversation/capabilities/chat/chat.viewmodel.ts
10159
10423
  function formatConversationChatText(result) {
10160
- const agentName = result.prompt.agent.name.trim();
10161
10424
  const reply2 = result.reply.trim();
10162
- const speakerPrefix = `${agentName}:`;
10163
- const normalizedReply = reply2.toLowerCase().startsWith(speakerPrefix.toLowerCase()) ? reply2 : `${speakerPrefix} ${reply2}`;
10164
10425
  const metadata = [`Session: ${result.sessionId}`];
10165
10426
  if (result.projectId !== void 0) {
10166
10427
  metadata.push(`Project: ${result.projectId}`);
@@ -10180,20 +10441,28 @@ function formatConversationChatText(result) {
10180
10441
  metadata.push(`Tokens: ${tokens.join(", ")}`);
10181
10442
  }
10182
10443
  }
10183
- return [normalizedReply, "", ...metadata].join("\n");
10444
+ return [reply2, "", ...metadata].join("\n");
10184
10445
  }
10185
10446
 
10186
10447
  // src/app/cli/rootConversation.ts
10187
- var cliConversationStatePath = {
10188
- namespace: "conversation",
10189
- segments: ["cli-state.json"]
10190
- };
10448
+ function sanitizeCliScope(scope) {
10449
+ return scope.replaceAll(/[^a-zA-Z0-9_-]+/g, "-").replaceAll(/^-+|-+$/g, "") || "default";
10450
+ }
10451
+ function currentCliSessionScope() {
10452
+ return process.env.AGENT_DEVKIT_CLI_SESSION_SCOPE ?? String(process.ppid);
10453
+ }
10454
+ function cliConversationStatePathForScope(scope) {
10455
+ return {
10456
+ namespace: "conversation",
10457
+ segments: [`cli-state-${sanitizeCliScope(scope)}.json`]
10458
+ };
10459
+ }
10191
10460
  function isCliConversationState(value) {
10192
10461
  const record = value;
10193
10462
  return typeof value === "object" && value !== null && "activeSessionId" in value && "schema" in value && typeof record.activeSessionId === "string" && record.activeSessionId.length > 0 && record.schema === "agent-devkit.cli-conversation-state/v1";
10194
10463
  }
10195
- async function loadActiveCliSessionId(dataStore, sessions) {
10196
- const state = await dataStore.readJson(cliConversationStatePath);
10464
+ async function loadActiveCliSessionId(dataStore, sessions, statePath) {
10465
+ const state = await dataStore.readJson(statePath);
10197
10466
  if (state.isErr()) {
10198
10467
  return void 0;
10199
10468
  }
@@ -10215,9 +10484,9 @@ async function loadActiveCliSessionId(dataStore, sessions) {
10215
10484
  }
10216
10485
  return result.session.id;
10217
10486
  }
10218
- async function saveActiveCliSessionId(dataStore, sessionId) {
10487
+ async function saveActiveCliSessionId(dataStore, sessionId, statePath) {
10219
10488
  await dataStore.writeJson(
10220
- cliConversationStatePath,
10489
+ statePath,
10221
10490
  {
10222
10491
  activeSessionId: sessionId,
10223
10492
  schema: "agent-devkit.cli-conversation-state/v1",
@@ -10267,9 +10536,11 @@ async function runRootConversation(message, options) {
10267
10536
  if (contextBindings.isErr()) {
10268
10537
  throw new Error(contextBindings.unwrapError());
10269
10538
  }
10539
+ const cliStatePath = cliConversationStatePathForScope(currentCliSessionScope());
10270
10540
  const activeSessionId = await loadActiveCliSessionId(
10271
10541
  dataStore,
10272
- contextBindings.unwrap().capabilities.sessions
10542
+ contextBindings.unwrap().capabilities.sessions,
10543
+ cliStatePath
10273
10544
  );
10274
10545
  const agent = new AgentRuntime({
10275
10546
  brainProvider: createBrainDockProvider({ stateDirectory: `${homeDirectory}/.agent-devkit` }),
@@ -10293,7 +10564,7 @@ async function runRootConversation(message, options) {
10293
10564
  if (payload.conversation === void 0 || !isConversationChatResult(rawConversation)) {
10294
10565
  throw new Error("Agent did not return a conversation result.");
10295
10566
  }
10296
- await saveActiveCliSessionId(dataStore, payload.conversation.sessionId);
10567
+ await saveActiveCliSessionId(dataStore, payload.conversation.sessionId, cliStatePath);
10297
10568
  console.log(formatConversationChatText(rawConversation));
10298
10569
  }
10299
10570
  function isConversationChatResult(value) {