agent-devkit 0.3.3 → 0.3.5

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.3",
11
+ version: "0.3.5",
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",
@@ -50,7 +50,7 @@ var package_default = {
50
50
  "release:verify": "node scripts/verify-release-alignment.mjs",
51
51
  test: "npm run test:architecture && npm run test:infra && npm run test:app && npm run test:modules",
52
52
  "test:app": "vitest run src/app/cli/commands src/app/mcp src/app/tui src/package.test.ts",
53
- "test:architecture": "vitest run src/architecture.test.ts src/modules/capability_registry.test.ts src/modules/capability_tool_runtime.test.ts src/modules/modules.registry.test.ts",
53
+ "test:architecture": "vitest run src/agent src/architecture.test.ts src/modules/capability_registry.test.ts src/modules/capability_tool_runtime.test.ts src/modules/modules.registry.test.ts",
54
54
  "test:infra": "vitest run src/infra",
55
55
  "test:module": "tsx scripts/test-modules.ts",
56
56
  "test:modules": "tsx scripts/test-modules.ts",
@@ -3648,6 +3648,43 @@ var ModelStore = class {
3648
3648
 
3649
3649
  // src/infra/brain/local_llama_provider.ts
3650
3650
  var nodeLlamaModuleName = "node-llama-cpp";
3651
+ function shouldSuppressNodeLlamaLog(line) {
3652
+ return line.startsWith("[node-llama-cpp]");
3653
+ }
3654
+ var defaultLocalGenerationOptions = {
3655
+ maxTokens: 512,
3656
+ temperature: 0.25,
3657
+ topK: 40,
3658
+ topP: 0.9
3659
+ };
3660
+ async function suppressNodeLlamaLogs(operation) {
3661
+ const originalWrite = process.stderr.write;
3662
+ let pending = "";
3663
+ const filteredWrite = ((chunk, encodingOrCallback, callback) => {
3664
+ const encoding = typeof encodingOrCallback === "string" ? encodingOrCallback : "utf8";
3665
+ const done = typeof encodingOrCallback === "function" ? encodingOrCallback : callback;
3666
+ const text2 = typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString(encoding) : String(chunk);
3667
+ const lines = `${pending}${text2}`.split(/\r?\n/);
3668
+ pending = lines.pop() ?? "";
3669
+ for (const line of lines) {
3670
+ if (!shouldSuppressNodeLlamaLog(line)) {
3671
+ originalWrite.call(process.stderr, `${line}
3672
+ `);
3673
+ }
3674
+ }
3675
+ done?.();
3676
+ return true;
3677
+ });
3678
+ process.stderr.write = filteredWrite;
3679
+ try {
3680
+ return await operation();
3681
+ } finally {
3682
+ if (pending.length > 0 && !shouldSuppressNodeLlamaLog(pending)) {
3683
+ originalWrite.call(process.stderr, pending);
3684
+ }
3685
+ process.stderr.write = originalWrite;
3686
+ }
3687
+ }
3651
3688
  async function loadNodeLlama() {
3652
3689
  try {
3653
3690
  return Result.ok(await import(nodeLlamaModuleName));
@@ -3658,8 +3695,11 @@ async function loadNodeLlama() {
3658
3695
  function systemPromptFrom(prompt) {
3659
3696
  const { agent } = prompt;
3660
3697
  const lines = [
3661
- `You are ${agent.name}.`,
3662
- `Behavior: ${agent.behavior}. Tone: ${agent.tone}. Detail level: ${agent.detailLevel}.`
3698
+ `You are ${agent.name}, the user's configured Agent DevKit personality.`,
3699
+ "You operate inside Agent DevKit, a local AI agent toolkit exposed through the `agent` CLI, TUI and MCP.",
3700
+ "Answer as the agent. Do not answer as the user, as a generic person, or as a generic chatbot.",
3701
+ `Behavior: ${agent.behavior}. Tone: ${agent.tone}. Detail level: ${agent.detailLevel}.`,
3702
+ "If the user asks personal questions about you, your personality or what you can do, answer from your configured persona and conversation abilities. Do not list generic human activities. Do not describe Agent DevKit internals unless the user explicitly asks about Agent DevKit, tools, commands, MCP, modules or project capabilities."
3663
3703
  ];
3664
3704
  if (agent.traits.length > 0) {
3665
3705
  lines.push(`Traits: ${agent.traits.join(", ")}.`);
@@ -3670,6 +3710,38 @@ function systemPromptFrom(prompt) {
3670
3710
  `Project: ${project.name}${project.description === void 0 ? "" : ` \u2014 ${project.description}`}.`
3671
3711
  );
3672
3712
  }
3713
+ const { session } = prompt.context;
3714
+ if (session !== void 0) {
3715
+ lines.push(
3716
+ `Session: ${session.id}. Title: ${session.title}. Messages: ${session.messageCount}.`
3717
+ );
3718
+ }
3719
+ if (prompt.context.knowledge.length > 0) {
3720
+ lines.push(
3721
+ "",
3722
+ "Agent DevKit knowledge:",
3723
+ ...prompt.context.knowledge.map((knowledge) => `- ${knowledge.content}`)
3724
+ );
3725
+ }
3726
+ if (prompt.tools.length > 0) {
3727
+ lines.push(
3728
+ "",
3729
+ "Available tools:",
3730
+ ...prompt.tools.map((tool) => `- ${tool.id} (${tool.risk}): ${tool.description}`)
3731
+ );
3732
+ }
3733
+ lines.push(
3734
+ "",
3735
+ "Tool policy:",
3736
+ `- Tool calls allowed: ${prompt.policies.allowToolCalls ? "yes" : "no"}.`,
3737
+ `- Approval required: ${prompt.policies.approvalRequired ? "yes" : "no"}.`,
3738
+ `- Max tool calls: ${prompt.policies.maxToolCalls}.`
3739
+ );
3740
+ if (!prompt.policies.allowToolCalls) {
3741
+ lines.push(
3742
+ "- In this mode, do not claim that you already executed actions. If the user asks for a concrete action, explain that direct tool execution is unavailable in this chat turn."
3743
+ );
3744
+ }
3673
3745
  lines.push(`Reply in ${prompt.output.language}.`);
3674
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}`);
3675
3747
  if (history.length > 0) {
@@ -3727,30 +3799,32 @@ var LocalLlamaBrainProvider = class {
3727
3799
  return Result.fail(nodeLlama.unwrapError());
3728
3800
  }
3729
3801
  try {
3730
- const llama = nodeLlama.unwrap();
3731
- const loadedModel = await this.#loadModel(llama, model.unwrap().path);
3732
- const context = await loadedModel.createContext();
3733
- const session = new llama.LlamaChatSession({
3734
- contextSequence: context.getSequence(),
3735
- systemPrompt: systemPromptFrom(request.prompt)
3736
- });
3737
- const text2 = await session.prompt(request.prompt.task.userMessage, {
3738
- grammar: await this.#grammarFor(options.jsonSchema),
3739
- maxTokens: request.options.maxOutputTokens,
3740
- onTextChunk: options.onToken,
3741
- seed: request.options.seed,
3742
- temperature: request.options.temperature,
3743
- topK: request.options.topK,
3744
- topP: request.options.topP
3745
- });
3746
- const outputTokens = text2.split(/\s+/g).filter(Boolean).length;
3747
- return Result.ok({
3748
- finishReason: "stop",
3749
- model: model.unwrap().id,
3750
- provider: "local",
3751
- schema: "agent-devkit.brain-response/v1",
3752
- text: text2,
3753
- usage: { outputTokens }
3802
+ return await suppressNodeLlamaLogs(async () => {
3803
+ const llama = nodeLlama.unwrap();
3804
+ const loadedModel = await this.#loadModel(llama, model.unwrap().path);
3805
+ const context = await loadedModel.createContext();
3806
+ const session = new llama.LlamaChatSession({
3807
+ contextSequence: context.getSequence(),
3808
+ systemPrompt: systemPromptFrom(request.prompt)
3809
+ });
3810
+ const text2 = await session.prompt(request.prompt.task.userMessage, {
3811
+ grammar: await this.#grammarFor(options.jsonSchema),
3812
+ maxTokens: request.options.maxOutputTokens ?? defaultLocalGenerationOptions.maxTokens,
3813
+ onTextChunk: options.onToken,
3814
+ seed: request.options.seed,
3815
+ temperature: request.options.temperature ?? defaultLocalGenerationOptions.temperature,
3816
+ topK: request.options.topK ?? defaultLocalGenerationOptions.topK,
3817
+ topP: request.options.topP ?? defaultLocalGenerationOptions.topP
3818
+ });
3819
+ const outputTokens = text2.split(/\s+/g).filter(Boolean).length;
3820
+ return Result.ok({
3821
+ finishReason: "stop",
3822
+ model: model.unwrap().id,
3823
+ provider: "local",
3824
+ schema: "agent-devkit.brain-response/v1",
3825
+ text: text2,
3826
+ usage: { outputTokens }
3827
+ });
3754
3828
  });
3755
3829
  } catch {
3756
3830
  return Result.fail(ErrorCodes.BrainProviderUnavailable);
@@ -5326,6 +5400,33 @@ function characterName2(character) {
5326
5400
  function compact(value) {
5327
5401
  return value.replaceAll(/\s+/g, " ").trim();
5328
5402
  }
5403
+ var agentDevKitConversationKnowledge = [
5404
+ {
5405
+ content: "Agent DevKit is a local AI agent toolkit exposed through the `agent` CLI, a TUI and MCP. It helps users operate this project through capabilities, local state, sessions, projects, preferences, personalization, logs, secrets, dependencies and local models.",
5406
+ id: "agent-devkit.identity",
5407
+ source: "conversation.chat"
5408
+ },
5409
+ {
5410
+ content: "When the user asks personal questions about you, your personality or what you can do, answer as the configured character using your behavior, tone, detail level and traits. Do not answer as a generic human and do not list unrelated human activities.",
5411
+ id: "agent-devkit.self-description-rule",
5412
+ source: "conversation.chat"
5413
+ },
5414
+ {
5415
+ content: "Only describe Agent DevKit internals, modules, tools, MCP, CLI commands or project capabilities when the user explicitly asks about Agent DevKit, the project, tools, commands, MCP or capabilities.",
5416
+ id: "agent-devkit.project-scope-rule",
5417
+ source: "conversation.chat"
5418
+ },
5419
+ {
5420
+ content: "This conversation mode can answer, keep session memory and use project context. Direct tool execution is disabled in this chat prompt.",
5421
+ id: "agent-devkit.chat-mode-limits",
5422
+ source: "conversation.chat"
5423
+ },
5424
+ {
5425
+ content: "Current capability areas include project doctor/init/reset, package update, preferences, themes, aliases, personalization characters, logs, encrypted secrets, dependency inspection/planning, models, projects, sessions and conversation.",
5426
+ id: "agent-devkit.capability-map",
5427
+ source: "conversation.chat"
5428
+ }
5429
+ ];
5329
5430
  var ConversationChatRepository = class {
5330
5431
  repositoryId = "conversation.chat.repository";
5331
5432
  #clock;
@@ -5470,7 +5571,7 @@ var ConversationChatRepository = class {
5470
5571
  traits: input.character.profile.traits
5471
5572
  },
5472
5573
  context: {
5473
- knowledge: [],
5574
+ knowledge: agentDevKitConversationKnowledge,
5474
5575
  project: input.project === void 0 ? void 0 : {
5475
5576
  description: input.project.description,
5476
5577
  id: input.project.id,
@@ -5575,6 +5676,38 @@ var conversationChatCapabilityConfig = defineCapabilityConfig({
5575
5676
  kind: "brain-assisted",
5576
5677
  risk: "writes-global-state"
5577
5678
  });
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";
5685
+ }
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);
5697
+ 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
+ }
5709
+ };
5710
+ }
5578
5711
  var ConversationChatService = class extends BaseCapabilityService {
5579
5712
  inputSchema = ConversationChatOptionsSchema;
5580
5713
  outputSchema = ConversationChatResultSchema;
@@ -5622,7 +5755,11 @@ var ConversationChatService = class extends BaseCapabilityService {
5622
5755
  prompt: prepared.unwrap().prompt,
5623
5756
  schema: "agent-devkit.brain-request/v1"
5624
5757
  };
5625
- const brain = onToken !== void 0 && this.#brainProvider.generateStream !== void 0 ? await this.#brainProvider.generateStream(request, onToken) : await this.#brainProvider.generate(request);
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
+ }
5626
5763
  if (brain.isErr()) {
5627
5764
  return Result.fail(brain.unwrapError());
5628
5765
  }
@@ -8016,7 +8153,7 @@ import {
8016
8153
  ListToolsRequestSchema
8017
8154
  } from "@modelcontextprotocol/sdk/types.js";
8018
8155
 
8019
- // src/infra/agent/agent_runtime.ts
8156
+ // src/agent/agent.brain.ts
8020
8157
  import { z as z23 } from "zod";
8021
8158
  var AgentDecisionSchema = z23.discriminatedUnion("action", [
8022
8159
  z23.object({ action: z23.literal("tool"), input: z23.unknown(), tool: z23.string().min(1) }),
@@ -8032,10 +8169,68 @@ var agentDecisionJsonSchema = {
8032
8169
  },
8033
8170
  required: ["action"]
8034
8171
  };
8172
+ function maxToolCallsFor(tools) {
8173
+ return Math.max(1, tools.length);
8174
+ }
8175
+ function buildToolDecisionPrompt(input) {
8176
+ const toolList = input.tools.map((tool) => `- ${tool.id} (${tool.risk}): ${tool.description}`).join("\n");
8177
+ const instruction = [
8178
+ `Tarefa do usu\xE1rio: ${input.task}`,
8179
+ "",
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.'
8184
+ ].join("\n");
8185
+ return AgentPromptSchema.parse({
8186
+ agent: {
8187
+ behavior: "balanced",
8188
+ characterId: "agent",
8189
+ detailLevel: "concise",
8190
+ name: "Agent",
8191
+ tone: "direct",
8192
+ traits: []
8193
+ },
8194
+ 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
+ ]
8201
+ },
8202
+ locale: "pt-BR",
8203
+ messages: input.transcript,
8204
+ output: { format: "json", language: "pt-BR" },
8205
+ policies: {
8206
+ allowToolCalls: true,
8207
+ approvalRequired: false,
8208
+ maxToolCalls: maxToolCallsFor(input.tools)
8209
+ },
8210
+ schema: "agent-devkit.prompt/v1",
8211
+ task: { userMessage: instruction },
8212
+ tools: input.tools.map((tool) => ({
8213
+ description: tool.description,
8214
+ id: tool.id,
8215
+ inputSchema: tool.inputSchema,
8216
+ risk: tool.risk
8217
+ }))
8218
+ });
8219
+ }
8220
+
8221
+ // src/agent/agent.policy.ts
8222
+ function isToolApproved(tool, input) {
8223
+ if (input.approvedTools !== void 0) {
8224
+ return input.approvedTools.includes(tool);
8225
+ }
8226
+ return input.approved === true;
8227
+ }
8228
+
8229
+ // src/agent/agent.loop.ts
8035
8230
  function summarize(value) {
8036
8231
  const text2 = typeof value === "string" ? value : JSON.stringify(value ?? "");
8037
8232
  const compact2 = text2.replaceAll(/\s+/g, " ").trim();
8038
- return compact2.length > 240 ? `${compact2.slice(0, 240)}\u2026` : compact2;
8233
+ return compact2.length > 240 ? `${compact2.slice(0, 240)}...` : compact2;
8039
8234
  }
8040
8235
  function observationSummary(result) {
8041
8236
  if (result.status === "succeeded") {
@@ -8043,7 +8238,7 @@ function observationSummary(result) {
8043
8238
  }
8044
8239
  return `${result.status}${result.error === void 0 ? "" : `: ${result.error.message}`}`;
8045
8240
  }
8046
- var AgentRuntime = class {
8241
+ var AgentToolLoop = class {
8047
8242
  #brain;
8048
8243
  #tools;
8049
8244
  constructor(options) {
@@ -8063,7 +8258,11 @@ var AgentRuntime = class {
8063
8258
  }));
8064
8259
  const tools = this.#tools.listTools();
8065
8260
  for (let step = 0; step < maxSteps; step += 1) {
8066
- const prompt = this.#buildPrompt(input.task, transcript, tools);
8261
+ const prompt = buildToolDecisionPrompt({
8262
+ task: input.task,
8263
+ tools,
8264
+ transcript
8265
+ });
8067
8266
  const request = {
8068
8267
  options: { provider: "local", role: "agent" },
8069
8268
  prompt,
@@ -8075,19 +8274,19 @@ var AgentRuntime = class {
8075
8274
  }
8076
8275
  const decision = AgentDecisionSchema.safeParse(structured.unwrap().json);
8077
8276
  if (!decision.success) {
8078
- return Result.ok({ reply: structured.unwrap().raw.trim(), steps });
8277
+ return Result.ok({ mode: "task", reply: structured.unwrap().raw.trim(), steps });
8079
8278
  }
8080
8279
  if (decision.data.action === "final") {
8081
8280
  input.onEvent?.({ reply: decision.data.reply, type: "final" });
8082
- return Result.ok({ reply: decision.data.reply, steps });
8281
+ return Result.ok({ mode: "task", reply: decision.data.reply, steps });
8083
8282
  }
8084
8283
  const tool = decision.data.tool;
8085
8284
  input.onEvent?.({ tool, type: "tool" });
8086
8285
  const execution = await this.#tools.execute({
8087
- approved: this.#isApproved(tool, input),
8286
+ approved: isToolApproved(tool, input),
8088
8287
  capabilityId: tool,
8089
8288
  input: decision.data.input,
8090
- interface: "agent",
8289
+ interface: input.interface ?? "agent",
8091
8290
  requestedBy: "agent.run"
8092
8291
  });
8093
8292
  const ok = execution.status === "succeeded";
@@ -8097,64 +8296,86 @@ var AgentRuntime = class {
8097
8296
  transcript.push({ content: `Observation from ${tool}: ${summary}`, role: "tool" });
8098
8297
  if (execution.status === "approval_required") {
8099
8298
  return Result.ok({
8299
+ mode: "task",
8100
8300
  reply: `A ferramenta ${tool} requer aprova\xE7\xE3o expl\xEDcita. Reexecute autorizando para continuar.`,
8101
8301
  steps
8102
8302
  });
8103
8303
  }
8104
8304
  }
8105
8305
  return Result.ok({
8306
+ mode: "task",
8106
8307
  reply: "Limite de passos do agente atingido sem uma resposta final.",
8107
8308
  steps
8108
8309
  });
8109
8310
  }
8110
- #isApproved(tool, input) {
8111
- if (input.approvedTools !== void 0) {
8112
- return input.approvedTools.includes(tool);
8311
+ };
8312
+
8313
+ // src/agent/agent.runtime.ts
8314
+ function textInput(input) {
8315
+ return (input.message ?? input.task ?? "").trim();
8316
+ }
8317
+ function resolveMode(input) {
8318
+ if (input.mode === "chat" || input.mode === "task") {
8319
+ return input.mode;
8320
+ }
8321
+ if (input.message !== void 0) {
8322
+ return "chat";
8323
+ }
8324
+ return "task";
8325
+ }
8326
+ function chatInput(input, message) {
8327
+ return {
8328
+ characterId: input.characterId,
8329
+ includeHistory: input.includeHistory,
8330
+ interface: input.interface ?? "cli",
8331
+ message,
8332
+ projectId: input.projectId,
8333
+ sessionId: input.sessionId
8334
+ };
8335
+ }
8336
+ var AgentRuntime = class {
8337
+ #conversation;
8338
+ #toolLoop;
8339
+ constructor(options) {
8340
+ this.#conversation = options.conversation;
8341
+ this.#toolLoop = new AgentToolLoop({
8342
+ brainProvider: options.brainProvider,
8343
+ toolRuntime: options.toolRuntime
8344
+ });
8345
+ }
8346
+ async run(input) {
8347
+ const message = textInput(input);
8348
+ if (message.length === 0) {
8349
+ return Result.fail(ErrorCodes.InvalidInput);
8113
8350
  }
8114
- return input.approved === true;
8351
+ const mode = resolveMode(input);
8352
+ if (mode === "chat") {
8353
+ return this.#runChat(input, message);
8354
+ }
8355
+ return this.#toolLoop.run({ ...input, task: message });
8115
8356
  }
8116
- #buildPrompt(task, transcript, tools) {
8117
- const toolList = tools.map((tool) => `- ${tool.id} (${tool.risk}): ${tool.description}`).join("\n");
8118
- const instruction = [
8119
- `Tarefa do usu\xE1rio: ${task}`,
8120
- "",
8121
- "Ferramentas dispon\xEDveis:",
8122
- toolList,
8123
- "",
8124
- '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.'
8125
- ].join("\n");
8126
- return AgentPromptSchema.parse({
8127
- agent: {
8128
- behavior: "balanced",
8129
- characterId: "agent",
8130
- detailLevel: "concise",
8131
- name: "Agent",
8132
- tone: "direct",
8133
- traits: []
8134
- },
8135
- context: { knowledge: [] },
8136
- locale: "pt-BR",
8137
- messages: transcript,
8138
- output: { format: "json", language: "pt-BR" },
8139
- policies: {
8140
- allowToolCalls: true,
8141
- approvalRequired: false,
8142
- maxToolCalls: maxToolCallsFor(tools)
8143
- },
8144
- schema: "agent-devkit.prompt/v1",
8145
- task: { userMessage: instruction },
8146
- tools: tools.map((tool) => ({
8147
- description: tool.description,
8148
- id: tool.id,
8149
- inputSchema: tool.inputSchema,
8150
- risk: tool.risk
8151
- }))
8357
+ async #runChat(input, message) {
8358
+ if (this.#conversation === void 0) {
8359
+ return Result.fail(ErrorCodes.BrainProviderUnavailable);
8360
+ }
8361
+ const result = await this.#conversation.chat(chatInput(input, message), {
8362
+ approved: input.approved,
8363
+ interface: input.interface ?? "cli",
8364
+ requestedBy: "agent.chat"
8365
+ });
8366
+ if (result.isErr()) {
8367
+ return Result.fail(result.unwrapError());
8368
+ }
8369
+ const conversation = result.unwrap();
8370
+ input.onEvent?.({ reply: conversation.reply, type: "final" });
8371
+ return Result.ok({
8372
+ conversation,
8373
+ mode: "chat",
8374
+ reply: conversation.reply,
8375
+ steps: []
8152
8376
  });
8153
8377
  }
8154
8378
  };
8155
- function maxToolCallsFor(tools) {
8156
- return Math.max(1, tools.length);
8157
- }
8158
8379
 
8159
8380
  // src/app/mcp/mcp_result_mapper.ts
8160
8381
  function inputSchemaWithAgentControl(tool) {
@@ -8309,7 +8530,7 @@ function createAgentMcpServer(options) {
8309
8530
  if (task.length === 0) {
8310
8531
  return { content: [{ type: "text", text: "Missing 'task'." }], isError: true };
8311
8532
  }
8312
- const run = await agent.run({ approvedTools, task });
8533
+ const run = await agent.run({ approvedTools, interface: "mcp", mode: "task", task });
8313
8534
  if (run.isErr()) {
8314
8535
  return {
8315
8536
  content: [{ type: "text", text: `Agent run failed: ${run.unwrapError()}` }],
@@ -9936,30 +10157,148 @@ import { homedir as homedir22 } from "os";
9936
10157
 
9937
10158
  // src/modules/conversation/capabilities/chat/chat.viewmodel.ts
9938
10159
  function formatConversationChatText(result) {
9939
- const lines = ["Agent:", result.reply, "", `Session: ${result.sessionId}`];
10160
+ const agentName = result.prompt.agent.name.trim();
10161
+ const reply2 = result.reply.trim();
10162
+ const speakerPrefix = `${agentName}:`;
10163
+ const normalizedReply = reply2.toLowerCase().startsWith(speakerPrefix.toLowerCase()) ? reply2 : `${speakerPrefix} ${reply2}`;
10164
+ const metadata = [`Session: ${result.sessionId}`];
9940
10165
  if (result.projectId !== void 0) {
9941
- lines.push(`Project: ${result.projectId}`);
10166
+ metadata.push(`Project: ${result.projectId}`);
9942
10167
  }
9943
- return lines.join("\n");
10168
+ if (result.brain.model !== void 0 || result.brain.provider !== void 0) {
10169
+ metadata.push(
10170
+ `Model: ${[result.brain.provider, result.brain.model].filter(Boolean).join("/")}`
10171
+ );
10172
+ }
10173
+ if (result.brain.usage !== void 0) {
10174
+ const tokens = [
10175
+ result.brain.usage.inputTokens === void 0 ? void 0 : `input ${result.brain.usage.inputTokens}`,
10176
+ result.brain.usage.outputTokens === void 0 ? void 0 : `output ${result.brain.usage.outputTokens}`,
10177
+ result.brain.usage.totalTokens === void 0 ? void 0 : `total ${result.brain.usage.totalTokens}`
10178
+ ].filter(Boolean);
10179
+ if (tokens.length > 0) {
10180
+ metadata.push(`Tokens: ${tokens.join(", ")}`);
10181
+ }
10182
+ }
10183
+ return [normalizedReply, "", ...metadata].join("\n");
9944
10184
  }
9945
10185
 
9946
10186
  // src/app/cli/rootConversation.ts
9947
- async function runRootConversation(message) {
10187
+ var cliConversationStatePath = {
10188
+ namespace: "conversation",
10189
+ segments: ["cli-state.json"]
10190
+ };
10191
+ function isCliConversationState(value) {
10192
+ const record = value;
10193
+ 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
+ }
10195
+ async function loadActiveCliSessionId(dataStore, sessions) {
10196
+ const state = await dataStore.readJson(cliConversationStatePath);
10197
+ if (state.isErr()) {
10198
+ return void 0;
10199
+ }
10200
+ const statePayload = state.unwrap();
10201
+ if (!isCliConversationState(statePayload)) {
10202
+ return void 0;
10203
+ }
10204
+ const current = await sessions.execute({
10205
+ action: "show",
10206
+ includeMessages: false,
10207
+ sessionId: statePayload.activeSessionId
10208
+ });
10209
+ if (current.isErr()) {
10210
+ return void 0;
10211
+ }
10212
+ const result = current.unwrap();
10213
+ if (result.action !== "show" || result.session.origin !== "cli" || result.session.status !== "active") {
10214
+ return void 0;
10215
+ }
10216
+ return result.session.id;
10217
+ }
10218
+ async function saveActiveCliSessionId(dataStore, sessionId) {
10219
+ await dataStore.writeJson(
10220
+ cliConversationStatePath,
10221
+ {
10222
+ activeSessionId: sessionId,
10223
+ schema: "agent-devkit.cli-conversation-state/v1",
10224
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
10225
+ },
10226
+ { atomic: true }
10227
+ );
10228
+ }
10229
+ function createConversationPort(chat) {
10230
+ return {
10231
+ chat: async (input, context) => {
10232
+ const result = await chat.invoke(
10233
+ {
10234
+ action: "send",
10235
+ characterId: input.characterId,
10236
+ includeHistory: input.includeHistory,
10237
+ message: input.message,
10238
+ projectId: input.projectId,
10239
+ sessionId: input.sessionId
10240
+ },
10241
+ context
10242
+ );
10243
+ return result.map((payload) => ({
10244
+ brain: payload.brain,
10245
+ projectId: payload.projectId,
10246
+ raw: payload,
10247
+ reply: payload.reply,
10248
+ sessionId: payload.sessionId
10249
+ }));
10250
+ }
10251
+ };
10252
+ }
10253
+ async function runRootConversation(message, options) {
10254
+ const homeDirectory = homedir22();
10255
+ const dataStore = new LocalAgentDataStore({
10256
+ rootDirectory: `${homeDirectory}/.agent-devkit/data`
10257
+ });
9948
10258
  const bindings = createConversationModuleBindings({
9949
- brainProvider: createBrainDockProvider({ stateDirectory: `${homedir22()}/.agent-devkit` }),
9950
- homeDirectory: homedir22()
10259
+ brainProvider: createBrainDockProvider({ stateDirectory: `${homeDirectory}/.agent-devkit` }),
10260
+ dataStore,
10261
+ homeDirectory
9951
10262
  });
10263
+ const contextBindings = createContextModuleBindings({ dataStore, homeDirectory });
9952
10264
  if (bindings.isErr()) {
9953
10265
  throw new Error(bindings.unwrapError());
9954
10266
  }
9955
- const result = await bindings.unwrap().capabilities.chat.execute({
9956
- action: "send",
9957
- message
10267
+ if (contextBindings.isErr()) {
10268
+ throw new Error(contextBindings.unwrapError());
10269
+ }
10270
+ const activeSessionId = await loadActiveCliSessionId(
10271
+ dataStore,
10272
+ contextBindings.unwrap().capabilities.sessions
10273
+ );
10274
+ const agent = new AgentRuntime({
10275
+ brainProvider: createBrainDockProvider({ stateDirectory: `${homeDirectory}/.agent-devkit` }),
10276
+ conversation: createConversationPort(bindings.unwrap().capabilities.chat),
10277
+ toolRuntime: createCliToolRuntime({
10278
+ currentVersion: options.currentVersion,
10279
+ packageName: options.packageName
10280
+ })
10281
+ });
10282
+ const result = await agent.run({
10283
+ interface: "cli",
10284
+ message,
10285
+ mode: "chat",
10286
+ sessionId: activeSessionId
9958
10287
  });
9959
10288
  if (result.isErr()) {
9960
10289
  throw new Error(result.unwrapError());
9961
10290
  }
9962
- console.log(formatConversationChatText(result.unwrap()));
10291
+ const payload = result.unwrap();
10292
+ const rawConversation = payload.conversation?.raw;
10293
+ if (payload.conversation === void 0 || !isConversationChatResult(rawConversation)) {
10294
+ throw new Error("Agent did not return a conversation result.");
10295
+ }
10296
+ await saveActiveCliSessionId(dataStore, payload.conversation.sessionId);
10297
+ console.log(formatConversationChatText(rawConversation));
10298
+ }
10299
+ function isConversationChatResult(value) {
10300
+ const candidate = value;
10301
+ return typeof value === "object" && value !== null && candidate.action === "send" && typeof candidate.reply === "string" && typeof candidate.sessionId === "string";
9963
10302
  }
9964
10303
 
9965
10304
  // src/infra/helpers/redaction.ts
@@ -10300,7 +10639,10 @@ program.name("agent").description(translator.t("cli.root.description")).version(
10300
10639
  program.error(translator.t("cli.root.removedChatCommand"));
10301
10640
  }
10302
10641
  if (initialPrompt.length > 0) {
10303
- await runRootConversation(initialPrompt);
10642
+ await runRootConversation(initialPrompt, {
10643
+ currentVersion: package_default.version,
10644
+ packageName: package_default.name
10645
+ });
10304
10646
  return;
10305
10647
  }
10306
10648
  await ensureFirstRunModel(translator);