@townco/agent 0.1.44 → 0.1.45

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.
Files changed (52) hide show
  1. package/dist/acp-server/adapter.d.ts +1 -0
  2. package/dist/acp-server/adapter.js +130 -9
  3. package/dist/acp-server/cli.d.ts +3 -1
  4. package/dist/acp-server/session-storage.d.ts +21 -1
  5. package/dist/acp-server/session-storage.js +19 -1
  6. package/dist/bin.js +0 -0
  7. package/dist/definition/index.d.ts +19 -0
  8. package/dist/definition/index.js +11 -0
  9. package/dist/definition/mcp.js +0 -1
  10. package/dist/definition/tools/todo.d.ts +49 -0
  11. package/dist/definition/tools/todo.js +80 -0
  12. package/dist/definition/tools/web_search.d.ts +4 -0
  13. package/dist/definition/tools/web_search.js +26 -0
  14. package/dist/dev-agent/index.d.ts +2 -0
  15. package/dist/dev-agent/index.js +18 -0
  16. package/dist/example.d.ts +2 -0
  17. package/dist/example.js +19 -0
  18. package/dist/index.js +13 -2
  19. package/dist/runner/agent-runner.d.ts +28 -2
  20. package/dist/runner/agent-runner.js +2 -1
  21. package/dist/runner/hooks/constants.d.ts +9 -0
  22. package/dist/runner/hooks/constants.js +19 -0
  23. package/dist/runner/hooks/executor.d.ts +23 -0
  24. package/dist/runner/hooks/executor.js +163 -0
  25. package/dist/runner/hooks/index.d.ts +5 -0
  26. package/dist/runner/hooks/index.js +5 -0
  27. package/dist/runner/hooks/loader.d.ts +5 -0
  28. package/dist/runner/hooks/loader.js +49 -0
  29. package/dist/runner/hooks/predefined/compaction-tool.d.ts +6 -0
  30. package/dist/runner/hooks/predefined/compaction-tool.js +42 -0
  31. package/dist/runner/hooks/registry.d.ts +14 -0
  32. package/dist/runner/hooks/registry.js +20 -0
  33. package/dist/runner/hooks/types.d.ts +144 -0
  34. package/dist/runner/hooks/types.js +33 -0
  35. package/dist/runner/index.d.ts +3 -1
  36. package/dist/runner/langchain/index.js +16 -10
  37. package/dist/runner/langchain/model-factory.js +3 -1
  38. package/dist/scaffold/claude-scaffold.js +8 -6
  39. package/dist/storage/index.js +3 -1
  40. package/dist/templates/index.d.ts +7 -0
  41. package/dist/templates/index.js +7 -2
  42. package/dist/test-script.js +3 -1
  43. package/dist/tsconfig.tsbuildinfo +1 -1
  44. package/index.ts +14 -2
  45. package/package.json +5 -5
  46. package/templates/index.ts +14 -2
  47. package/dist/acp-server/test-acp-summarize.d.ts +0 -7
  48. package/dist/acp-server/test-acp-summarize.js +0 -127
  49. package/dist/acp-server/test-summarizer.d.ts +0 -7
  50. package/dist/acp-server/test-summarizer.js +0 -170
  51. package/dist/acp-server/tool-summarizer.d.ts +0 -125
  52. package/dist/acp-server/tool-summarizer.js +0 -182
@@ -147,15 +147,14 @@ export class LangchainAgent {
147
147
  agentConfig.systemPrompt = `${agentConfig.systemPrompt ?? ""}\n\n${TODO_WRITE_INSTRUCTIONS}`;
148
148
  }
149
149
  const agent = createAgent(agentConfig);
150
- // Build messages from session history if available, otherwise use just the prompt
150
+ // Build messages from context history if available, otherwise use just the prompt
151
151
  let messages;
152
- if (req.sessionMessages && req.sessionMessages.length > 0) {
153
- // Use session message history - convert to LangChain format
154
- // Only include messages BEFORE the current user message (exclude the last one since it's the current prompt)
155
- const historyMessages = req.sessionMessages.slice(0, -1);
156
- messages = historyMessages.map((msg) => ({
152
+ if (req.contextMessages && req.contextMessages.length > 0) {
153
+ // Use context messages (already resolved from context entries)
154
+ // Convert to LangChain format
155
+ messages = req.contextMessages.map((msg) => ({
157
156
  type: msg.role === "user" ? "human" : "ai",
158
- // Extract text from content blocks (ignore tool call blocks for LLM context)
157
+ // Extract text from content blocks
159
158
  content: msg.content
160
159
  .filter((block) => block.type === "text")
161
160
  .map((block) => block.text)
@@ -172,7 +171,7 @@ export class LangchainAgent {
172
171
  });
173
172
  }
174
173
  else {
175
- // Fallback: No session history, use just the prompt (legacy behavior)
174
+ // Fallback: No context history, use just the prompt
176
175
  messages = req.prompt
177
176
  .filter((promptMsg) => promptMsg.type === "text")
178
177
  .map((promptMsg) => ({
@@ -282,7 +281,12 @@ export class LangchainAgent {
282
281
  : typeof aiMessage.content === "string"
283
282
  ? aiMessage.content.length
284
283
  : -1;
285
- console.log("DEBUG agent: messageTokenUsage:", JSON.stringify(messageTokenUsage), "contentType:", contentType, "isArray:", contentIsArray, "length:", contentLength);
284
+ _logger.debug("messageTokenUsage", {
285
+ messageTokenUsage,
286
+ contentType,
287
+ isArray: contentIsArray,
288
+ length: contentLength,
289
+ });
286
290
  }
287
291
  // If we have tokenUsage but no content, send a token-only chunk
288
292
  if (messageTokenUsage &&
@@ -290,7 +294,9 @@ export class LangchainAgent {
290
294
  ? aiMessage.content === ""
291
295
  : Array.isArray(aiMessage.content) &&
292
296
  aiMessage.content.length === 0)) {
293
- console.log("DEBUG agent: sending token-only chunk:", JSON.stringify(messageTokenUsage));
297
+ _logger.debug("sending token-only chunk", {
298
+ messageTokenUsage,
299
+ });
294
300
  const msgToYield = {
295
301
  sessionUpdate: "agent_message_chunk",
296
302
  content: {
@@ -1,6 +1,8 @@
1
1
  import { ChatAnthropic } from "@langchain/anthropic";
2
2
  import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
3
3
  import { ChatVertexAI } from "@langchain/google-vertexai";
4
+ import { createLogger } from "@townco/core";
5
+ const logger = createLogger("model-factory");
4
6
  /**
5
7
  * Detects the provider from a model string and returns the appropriate
6
8
  * LangChain chat model instance.
@@ -93,7 +95,7 @@ export function createModelFromString(modelString) {
93
95
  });
94
96
  default:
95
97
  // Fallback to Anthropic for unknown providers (backward compatibility)
96
- console.warn(`Unknown provider "${provider}" in model string "${modelString}". Defaulting to Anthropic.`);
98
+ logger.warn(`Unknown provider "${provider}" in model string "${modelString}". Defaulting to Anthropic.`);
97
99
  return new ChatAnthropic({
98
100
  model: modelString,
99
101
  });
@@ -2,8 +2,10 @@ import { existsSync } from "node:fs";
2
2
  import { appendFile, readFile, writeFile } from "node:fs/promises";
3
3
  import { dirname, join } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
+ import { createLogger } from "@townco/core";
5
6
  const __filename = fileURLToPath(import.meta.url);
6
7
  const __dirname = dirname(__filename);
8
+ const logger = createLogger("claude-scaffold");
7
9
  /**
8
10
  * Initialize Claude Code workspace integration by creating AGENTS.town.md
9
11
  * and adding references to it in CLAUDE.md and AGENTS.md.
@@ -29,30 +31,30 @@ export async function initForClaudeCode(targetPath) {
29
31
  const townContent = await readFile(appendTemplatePath, "utf-8");
30
32
  // Create AGENTS.town.md with the Town-specific content
31
33
  await writeFile(agentsTownMdPath, townContent, "utf-8");
32
- console.log("✓ Created AGENTS.town.md");
34
+ logger.info("✓ Created AGENTS.town.md");
33
35
  // Add reference to AGENTS.town.md in both CLAUDE.md and AGENTS.md
34
36
  const referenceText = "\n\nThis repo uses the Town agent SDK -- please reference @AGENTS.town.md for more information\n";
35
37
  // Handle CLAUDE.md
36
38
  if (existsSync(claudeMdPath)) {
37
39
  // CLAUDE.md exists, append reference
38
40
  await appendFile(claudeMdPath, referenceText);
39
- console.log("✓ Added Town SDK reference to CLAUDE.md");
41
+ logger.info("✓ Added Town SDK reference to CLAUDE.md");
40
42
  }
41
43
  else {
42
44
  // CLAUDE.md doesn't exist, create it with just the reference
43
45
  await writeFile(claudeMdPath, `${referenceText.trim()}\n`, "utf-8");
44
- console.log("✓ Created CLAUDE.md with Town SDK reference");
46
+ logger.info("✓ Created CLAUDE.md with Town SDK reference");
45
47
  }
46
48
  // Handle AGENTS.md
47
49
  if (existsSync(agentsMdPath)) {
48
50
  // AGENTS.md exists, append reference
49
51
  await appendFile(agentsMdPath, referenceText);
50
- console.log("✓ Added Town SDK reference to AGENTS.md");
52
+ logger.info("✓ Added Town SDK reference to AGENTS.md");
51
53
  }
52
54
  else {
53
55
  // AGENTS.md doesn't exist, create it with just the reference
54
56
  await writeFile(agentsMdPath, `${referenceText.trim()}\n`, "utf-8");
55
- console.log("✓ Created AGENTS.md with Town SDK reference");
57
+ logger.info("✓ Created AGENTS.md with Town SDK reference");
56
58
  }
57
- console.log("✓ Claude Code workspace initialized");
59
+ logger.info("✓ Claude Code workspace initialized");
58
60
  }
@@ -1,7 +1,9 @@
1
1
  import { mkdir, readdir, rm, stat } from "node:fs/promises";
2
2
  import { homedir } from "node:os";
3
3
  import { dirname, join } from "node:path";
4
+ import { createLogger } from "@townco/core";
4
5
  const AGENTS_DIR = join(homedir(), ".config", "town", "agents");
6
+ const logger = createLogger("storage");
5
7
  /**
6
8
  * Get the base directory where all agents are stored
7
9
  */
@@ -39,7 +41,7 @@ export async function listAgents() {
39
41
  .map((entry) => entry.name);
40
42
  }
41
43
  catch (error) {
42
- console.error("Error listing agents:", error);
44
+ logger.error("Error listing agents", { error });
43
45
  return [];
44
46
  }
45
47
  }
@@ -17,6 +17,13 @@ export interface TemplateVars {
17
17
  }>;
18
18
  systemPrompt: string | null;
19
19
  hasWebSearch: boolean;
20
+ hooks?: Array<{
21
+ type: "context_size";
22
+ setting?: {
23
+ threshold: number;
24
+ } | undefined;
25
+ callback: string;
26
+ }> | undefined;
20
27
  }
21
28
  export declare function getTemplateVars(name: string, definition: AgentDefinition): TemplateVars;
22
29
  export declare function generatePackageJson(vars: TemplateVars): string;
@@ -7,6 +7,7 @@ export function getTemplateVars(name, definition) {
7
7
  tools,
8
8
  systemPrompt: definition.systemPrompt,
9
9
  hasWebSearch: tools.some((tool) => typeof tool === "string" && tool === "web_search"),
10
+ hooks: definition.hooks,
10
11
  };
11
12
  }
12
13
  export function generatePackageJson(vars) {
@@ -47,10 +48,14 @@ export async function generateIndexTs(vars) {
47
48
  model: vars.model,
48
49
  systemPrompt: vars.systemPrompt,
49
50
  tools: vars.tools,
51
+ hooks: vars.hooks,
50
52
  };
51
53
  return prettier.format(`import { makeHttpTransport, makeStdioTransport } from "@townco/agent/acp-server";
52
54
  import type { AgentDefinition } from "@townco/agent/definition";
53
55
  import { basename } from "node:path";
56
+ import { createLogger } from "@townco/core";
57
+
58
+ const logger = createLogger("agent-index");
54
59
 
55
60
  // Load agent definition from JSON file
56
61
  const agent: AgentDefinition = ${JSON.stringify(agentDef)};
@@ -61,14 +66,14 @@ const transport = process.argv[2] || "stdio";
61
66
  const agentDir = process.cwd();
62
67
  const agentName = basename(agentDir);
63
68
 
64
- console.log("[agent] Configuration:", { transport, agentDir, agentName });
69
+ logger.info("Configuration", { transport, agentDir, agentName });
65
70
 
66
71
  if (transport === "http") {
67
72
  makeHttpTransport(agent, agentDir, agentName);
68
73
  } else if (transport === "stdio") {
69
74
  makeStdioTransport(agent);
70
75
  } else {
71
- console.error(\`Invalid transport: \${transport}\`);
76
+ logger.error(\`Invalid transport: \${transport}\`);
72
77
  process.exit(1);
73
78
  }
74
79
  `, { parser: "typescript" });
@@ -1,4 +1,6 @@
1
+ import { createLogger } from "@townco/core";
1
2
  import { LangchainAgent } from "./runner/langchain";
3
+ const logger = createLogger("test-script");
2
4
  const agent = new LangchainAgent({
3
5
  model: "claude-sonnet-4-5-20250929",
4
6
  systemPrompt: "You are a helpful assistant.",
@@ -14,5 +16,5 @@ for await (const event of agent.invoke({
14
16
  sessionId: "test-session",
15
17
  messageId: "test-message-1",
16
18
  })) {
17
- console.log(event);
19
+ logger.info("Event received", { event });
18
20
  }