agent-devkit 0.3.4 → 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/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Agent DevKit is a TypeScript/Node rewrite of the `agent-devkit` package.
4
4
 
5
5
  The public npm package is `agent-devkit`; the canonical command is `agent`.
6
- Version `0.3.4` starts a new implementation focused on a maintainable CLI/TUI
6
+ Version `0.3.5` starts a new implementation focused on a maintainable CLI/TUI
7
7
  runtime while preserving the product direction from the legacy `0.3.x` line.
8
8
 
9
9
  ## Status
@@ -145,7 +145,7 @@ Rules:
145
145
  ## Distribution
146
146
 
147
147
  The package is npm-first and publishes the `agent` binary from `dist/main.js`.
148
- Standalone binaries are outside the initial `0.3.4` scope.
148
+ Standalone binaries are outside the initial `0.3.5` scope.
149
149
 
150
150
  Installing the npm package must not create runtime folders or project files.
151
151
  State is created only when the user runs the tool:
@@ -187,8 +187,8 @@ agent reset --dry-run
187
187
  agent reset --yes
188
188
  agent reset -g --dry-run
189
189
  agent update --latest --dry-run
190
- agent update 0.3.4 --dry-run
191
- agent update 0.3.4 --yes
190
+ agent update 0.3.5 --dry-run
191
+ agent update 0.3.5 --yes
192
192
  agent preferences
193
193
  agent preferences --json
194
194
  agent preferences themes
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.4",
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",
@@ -8153,7 +8153,7 @@ import {
8153
8153
  ListToolsRequestSchema
8154
8154
  } from "@modelcontextprotocol/sdk/types.js";
8155
8155
 
8156
- // src/infra/agent/agent_runtime.ts
8156
+ // src/agent/agent.brain.ts
8157
8157
  import { z as z23 } from "zod";
8158
8158
  var AgentDecisionSchema = z23.discriminatedUnion("action", [
8159
8159
  z23.object({ action: z23.literal("tool"), input: z23.unknown(), tool: z23.string().min(1) }),
@@ -8169,10 +8169,68 @@ var agentDecisionJsonSchema = {
8169
8169
  },
8170
8170
  required: ["action"]
8171
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
8172
8230
  function summarize(value) {
8173
8231
  const text2 = typeof value === "string" ? value : JSON.stringify(value ?? "");
8174
8232
  const compact2 = text2.replaceAll(/\s+/g, " ").trim();
8175
- return compact2.length > 240 ? `${compact2.slice(0, 240)}\u2026` : compact2;
8233
+ return compact2.length > 240 ? `${compact2.slice(0, 240)}...` : compact2;
8176
8234
  }
8177
8235
  function observationSummary(result) {
8178
8236
  if (result.status === "succeeded") {
@@ -8180,7 +8238,7 @@ function observationSummary(result) {
8180
8238
  }
8181
8239
  return `${result.status}${result.error === void 0 ? "" : `: ${result.error.message}`}`;
8182
8240
  }
8183
- var AgentRuntime = class {
8241
+ var AgentToolLoop = class {
8184
8242
  #brain;
8185
8243
  #tools;
8186
8244
  constructor(options) {
@@ -8200,7 +8258,11 @@ var AgentRuntime = class {
8200
8258
  }));
8201
8259
  const tools = this.#tools.listTools();
8202
8260
  for (let step = 0; step < maxSteps; step += 1) {
8203
- const prompt = this.#buildPrompt(input.task, transcript, tools);
8261
+ const prompt = buildToolDecisionPrompt({
8262
+ task: input.task,
8263
+ tools,
8264
+ transcript
8265
+ });
8204
8266
  const request = {
8205
8267
  options: { provider: "local", role: "agent" },
8206
8268
  prompt,
@@ -8212,19 +8274,19 @@ var AgentRuntime = class {
8212
8274
  }
8213
8275
  const decision = AgentDecisionSchema.safeParse(structured.unwrap().json);
8214
8276
  if (!decision.success) {
8215
- return Result.ok({ reply: structured.unwrap().raw.trim(), steps });
8277
+ return Result.ok({ mode: "task", reply: structured.unwrap().raw.trim(), steps });
8216
8278
  }
8217
8279
  if (decision.data.action === "final") {
8218
8280
  input.onEvent?.({ reply: decision.data.reply, type: "final" });
8219
- return Result.ok({ reply: decision.data.reply, steps });
8281
+ return Result.ok({ mode: "task", reply: decision.data.reply, steps });
8220
8282
  }
8221
8283
  const tool = decision.data.tool;
8222
8284
  input.onEvent?.({ tool, type: "tool" });
8223
8285
  const execution = await this.#tools.execute({
8224
- approved: this.#isApproved(tool, input),
8286
+ approved: isToolApproved(tool, input),
8225
8287
  capabilityId: tool,
8226
8288
  input: decision.data.input,
8227
- interface: "agent",
8289
+ interface: input.interface ?? "agent",
8228
8290
  requestedBy: "agent.run"
8229
8291
  });
8230
8292
  const ok = execution.status === "succeeded";
@@ -8234,64 +8296,86 @@ var AgentRuntime = class {
8234
8296
  transcript.push({ content: `Observation from ${tool}: ${summary}`, role: "tool" });
8235
8297
  if (execution.status === "approval_required") {
8236
8298
  return Result.ok({
8299
+ mode: "task",
8237
8300
  reply: `A ferramenta ${tool} requer aprova\xE7\xE3o expl\xEDcita. Reexecute autorizando para continuar.`,
8238
8301
  steps
8239
8302
  });
8240
8303
  }
8241
8304
  }
8242
8305
  return Result.ok({
8306
+ mode: "task",
8243
8307
  reply: "Limite de passos do agente atingido sem uma resposta final.",
8244
8308
  steps
8245
8309
  });
8246
8310
  }
8247
- #isApproved(tool, input) {
8248
- if (input.approvedTools !== void 0) {
8249
- 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);
8350
+ }
8351
+ const mode = resolveMode(input);
8352
+ if (mode === "chat") {
8353
+ return this.#runChat(input, message);
8250
8354
  }
8251
- return input.approved === true;
8355
+ return this.#toolLoop.run({ ...input, task: message });
8252
8356
  }
8253
- #buildPrompt(task, transcript, tools) {
8254
- const toolList = tools.map((tool) => `- ${tool.id} (${tool.risk}): ${tool.description}`).join("\n");
8255
- const instruction = [
8256
- `Tarefa do usu\xE1rio: ${task}`,
8257
- "",
8258
- "Ferramentas dispon\xEDveis:",
8259
- toolList,
8260
- "",
8261
- '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.'
8262
- ].join("\n");
8263
- return AgentPromptSchema.parse({
8264
- agent: {
8265
- behavior: "balanced",
8266
- characterId: "agent",
8267
- detailLevel: "concise",
8268
- name: "Agent",
8269
- tone: "direct",
8270
- traits: []
8271
- },
8272
- context: { knowledge: [] },
8273
- locale: "pt-BR",
8274
- messages: transcript,
8275
- output: { format: "json", language: "pt-BR" },
8276
- policies: {
8277
- allowToolCalls: true,
8278
- approvalRequired: false,
8279
- maxToolCalls: maxToolCallsFor(tools)
8280
- },
8281
- schema: "agent-devkit.prompt/v1",
8282
- task: { userMessage: instruction },
8283
- tools: tools.map((tool) => ({
8284
- description: tool.description,
8285
- id: tool.id,
8286
- inputSchema: tool.inputSchema,
8287
- risk: tool.risk
8288
- }))
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: []
8289
8376
  });
8290
8377
  }
8291
8378
  };
8292
- function maxToolCallsFor(tools) {
8293
- return Math.max(1, tools.length);
8294
- }
8295
8379
 
8296
8380
  // src/app/mcp/mcp_result_mapper.ts
8297
8381
  function inputSchemaWithAgentControl(tool) {
@@ -8446,7 +8530,7 @@ function createAgentMcpServer(options) {
8446
8530
  if (task.length === 0) {
8447
8531
  return { content: [{ type: "text", text: "Missing 'task'." }], isError: true };
8448
8532
  }
8449
- const run = await agent.run({ approvedTools, task });
8533
+ const run = await agent.run({ approvedTools, interface: "mcp", mode: "task", task });
8450
8534
  if (run.isErr()) {
8451
8535
  return {
8452
8536
  content: [{ type: "text", text: `Agent run failed: ${run.unwrapError()}` }],
@@ -10142,7 +10226,31 @@ async function saveActiveCliSessionId(dataStore, sessionId) {
10142
10226
  { atomic: true }
10143
10227
  );
10144
10228
  }
10145
- async function runRootConversation(message) {
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) {
10146
10254
  const homeDirectory = homedir22();
10147
10255
  const dataStore = new LocalAgentDataStore({
10148
10256
  rootDirectory: `${homeDirectory}/.agent-devkit/data`
@@ -10163,17 +10271,34 @@ async function runRootConversation(message) {
10163
10271
  dataStore,
10164
10272
  contextBindings.unwrap().capabilities.sessions
10165
10273
  );
10166
- const result = await bindings.unwrap().capabilities.chat.execute({
10167
- action: "send",
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",
10168
10284
  message,
10285
+ mode: "chat",
10169
10286
  sessionId: activeSessionId
10170
10287
  });
10171
10288
  if (result.isErr()) {
10172
10289
  throw new Error(result.unwrapError());
10173
10290
  }
10174
10291
  const payload = result.unwrap();
10175
- await saveActiveCliSessionId(dataStore, payload.sessionId);
10176
- console.log(formatConversationChatText(payload));
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";
10177
10302
  }
10178
10303
 
10179
10304
  // src/infra/helpers/redaction.ts
@@ -10514,7 +10639,10 @@ program.name("agent").description(translator.t("cli.root.description")).version(
10514
10639
  program.error(translator.t("cli.root.removedChatCommand"));
10515
10640
  }
10516
10641
  if (initialPrompt.length > 0) {
10517
- await runRootConversation(initialPrompt);
10642
+ await runRootConversation(initialPrompt, {
10643
+ currentVersion: package_default.version,
10644
+ packageName: package_default.name
10645
+ });
10518
10646
  return;
10519
10647
  }
10520
10648
  await ensureFirstRunModel(translator);