agent-devkit 0.3.3 → 0.3.4

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.3` starts a new implementation focused on a maintainable CLI/TUI
6
+ Version `0.3.4` 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.3` scope.
148
+ Standalone binaries are outside the initial `0.3.4` 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.3 --dry-run
191
- agent update 0.3.3 --yes
190
+ agent update 0.3.4 --dry-run
191
+ agent update 0.3.4 --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.3",
11
+ version: "0.3.4",
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",
@@ -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
  }
@@ -9936,30 +10073,107 @@ import { homedir as homedir22 } from "os";
9936
10073
 
9937
10074
  // src/modules/conversation/capabilities/chat/chat.viewmodel.ts
9938
10075
  function formatConversationChatText(result) {
9939
- const lines = ["Agent:", result.reply, "", `Session: ${result.sessionId}`];
10076
+ const agentName = result.prompt.agent.name.trim();
10077
+ const reply2 = result.reply.trim();
10078
+ const speakerPrefix = `${agentName}:`;
10079
+ const normalizedReply = reply2.toLowerCase().startsWith(speakerPrefix.toLowerCase()) ? reply2 : `${speakerPrefix} ${reply2}`;
10080
+ const metadata = [`Session: ${result.sessionId}`];
9940
10081
  if (result.projectId !== void 0) {
9941
- lines.push(`Project: ${result.projectId}`);
10082
+ metadata.push(`Project: ${result.projectId}`);
9942
10083
  }
9943
- return lines.join("\n");
10084
+ if (result.brain.model !== void 0 || result.brain.provider !== void 0) {
10085
+ metadata.push(
10086
+ `Model: ${[result.brain.provider, result.brain.model].filter(Boolean).join("/")}`
10087
+ );
10088
+ }
10089
+ if (result.brain.usage !== void 0) {
10090
+ const tokens = [
10091
+ result.brain.usage.inputTokens === void 0 ? void 0 : `input ${result.brain.usage.inputTokens}`,
10092
+ result.brain.usage.outputTokens === void 0 ? void 0 : `output ${result.brain.usage.outputTokens}`,
10093
+ result.brain.usage.totalTokens === void 0 ? void 0 : `total ${result.brain.usage.totalTokens}`
10094
+ ].filter(Boolean);
10095
+ if (tokens.length > 0) {
10096
+ metadata.push(`Tokens: ${tokens.join(", ")}`);
10097
+ }
10098
+ }
10099
+ return [normalizedReply, "", ...metadata].join("\n");
9944
10100
  }
9945
10101
 
9946
10102
  // src/app/cli/rootConversation.ts
10103
+ var cliConversationStatePath = {
10104
+ namespace: "conversation",
10105
+ segments: ["cli-state.json"]
10106
+ };
10107
+ function isCliConversationState(value) {
10108
+ const record = value;
10109
+ 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";
10110
+ }
10111
+ async function loadActiveCliSessionId(dataStore, sessions) {
10112
+ const state = await dataStore.readJson(cliConversationStatePath);
10113
+ if (state.isErr()) {
10114
+ return void 0;
10115
+ }
10116
+ const statePayload = state.unwrap();
10117
+ if (!isCliConversationState(statePayload)) {
10118
+ return void 0;
10119
+ }
10120
+ const current = await sessions.execute({
10121
+ action: "show",
10122
+ includeMessages: false,
10123
+ sessionId: statePayload.activeSessionId
10124
+ });
10125
+ if (current.isErr()) {
10126
+ return void 0;
10127
+ }
10128
+ const result = current.unwrap();
10129
+ if (result.action !== "show" || result.session.origin !== "cli" || result.session.status !== "active") {
10130
+ return void 0;
10131
+ }
10132
+ return result.session.id;
10133
+ }
10134
+ async function saveActiveCliSessionId(dataStore, sessionId) {
10135
+ await dataStore.writeJson(
10136
+ cliConversationStatePath,
10137
+ {
10138
+ activeSessionId: sessionId,
10139
+ schema: "agent-devkit.cli-conversation-state/v1",
10140
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
10141
+ },
10142
+ { atomic: true }
10143
+ );
10144
+ }
9947
10145
  async function runRootConversation(message) {
10146
+ const homeDirectory = homedir22();
10147
+ const dataStore = new LocalAgentDataStore({
10148
+ rootDirectory: `${homeDirectory}/.agent-devkit/data`
10149
+ });
9948
10150
  const bindings = createConversationModuleBindings({
9949
- brainProvider: createBrainDockProvider({ stateDirectory: `${homedir22()}/.agent-devkit` }),
9950
- homeDirectory: homedir22()
10151
+ brainProvider: createBrainDockProvider({ stateDirectory: `${homeDirectory}/.agent-devkit` }),
10152
+ dataStore,
10153
+ homeDirectory
9951
10154
  });
10155
+ const contextBindings = createContextModuleBindings({ dataStore, homeDirectory });
9952
10156
  if (bindings.isErr()) {
9953
10157
  throw new Error(bindings.unwrapError());
9954
10158
  }
10159
+ if (contextBindings.isErr()) {
10160
+ throw new Error(contextBindings.unwrapError());
10161
+ }
10162
+ const activeSessionId = await loadActiveCliSessionId(
10163
+ dataStore,
10164
+ contextBindings.unwrap().capabilities.sessions
10165
+ );
9955
10166
  const result = await bindings.unwrap().capabilities.chat.execute({
9956
10167
  action: "send",
9957
- message
10168
+ message,
10169
+ sessionId: activeSessionId
9958
10170
  });
9959
10171
  if (result.isErr()) {
9960
10172
  throw new Error(result.unwrapError());
9961
10173
  }
9962
- console.log(formatConversationChatText(result.unwrap()));
10174
+ const payload = result.unwrap();
10175
+ await saveActiveCliSessionId(dataStore, payload.sessionId);
10176
+ console.log(formatConversationChatText(payload));
9963
10177
  }
9964
10178
 
9965
10179
  // src/infra/helpers/redaction.ts