@townco/agent 0.1.31 → 0.1.32

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/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { basename } from "node:path";
1
2
  import { makeHttpTransport, makeStdioTransport } from "./acp-server";
2
3
  import { makeSubagentsTool } from "./utils";
3
4
  const exampleAgent = {
@@ -23,8 +24,11 @@ const exampleAgent = {
23
24
  };
24
25
  // Parse transport type from command line argument
25
26
  const transport = process.argv[2] || "stdio";
27
+ // Get agent directory and name for session storage
28
+ const agentDir = process.cwd();
29
+ const agentName = basename(agentDir);
26
30
  if (transport === "http") {
27
- makeHttpTransport(exampleAgent);
31
+ makeHttpTransport(exampleAgent, agentDir, agentName);
28
32
  }
29
33
  else if (transport === "stdio") {
30
34
  makeStdioTransport(exampleAgent);
@@ -29,9 +29,15 @@ export declare const zAgentRunnerParams: z.ZodObject<{
29
29
  }, z.core.$strip>]>>>;
30
30
  }, z.core.$strip>;
31
31
  export type CreateAgentRunnerParams = z.infer<typeof zAgentRunnerParams>;
32
+ export interface SessionMessage {
33
+ role: "user" | "assistant";
34
+ content: string;
35
+ timestamp: string;
36
+ }
32
37
  export type InvokeRequest = Omit<PromptRequest, "_meta"> & {
33
38
  messageId: string;
34
39
  sessionMeta?: Record<string, unknown>;
40
+ sessionMessages?: SessionMessage[];
35
41
  };
36
42
  export interface TokenUsage {
37
43
  inputTokens?: number;
@@ -1,4 +1,6 @@
1
1
  import type { AgentDefinition } from "../definition";
2
2
  import { type AgentRunner } from "./agent-runner";
3
3
  export type { AgentRunner };
4
- export declare const makeRunnerFromDefinition: (definition: AgentDefinition) => AgentRunner;
4
+ export declare const makeRunnerFromDefinition: (
5
+ definition: AgentDefinition,
6
+ ) => AgentRunner;
@@ -1,18 +1,22 @@
1
1
  import { zAgentRunnerParams } from "./agent-runner";
2
2
  import { LangchainAgent } from "./langchain";
3
3
  export const makeRunnerFromDefinition = (definition) => {
4
- const agentRunnerParams = zAgentRunnerParams.safeParse(definition);
5
- if (!agentRunnerParams.success) {
6
- throw new Error(`Invalid agent definition: ${agentRunnerParams.error.message}`);
7
- }
8
- switch (definition.harnessImplementation) {
9
- case undefined:
10
- case "langchain": {
11
- return new LangchainAgent(agentRunnerParams.data);
12
- }
13
- default: {
14
- const _exhaustiveCheck = definition.harnessImplementation;
15
- throw new Error(`Unsupported harness implementation: ${definition.harnessImplementation}`);
16
- }
17
- }
4
+ const agentRunnerParams = zAgentRunnerParams.safeParse(definition);
5
+ if (!agentRunnerParams.success) {
6
+ throw new Error(
7
+ `Invalid agent definition: ${agentRunnerParams.error.message}`,
8
+ );
9
+ }
10
+ switch (definition.harnessImplementation) {
11
+ case undefined:
12
+ case "langchain": {
13
+ return new LangchainAgent(agentRunnerParams.data);
14
+ }
15
+ default: {
16
+ const _exhaustiveCheck = definition.harnessImplementation;
17
+ throw new Error(
18
+ `Unsupported harness implementation: ${definition.harnessImplementation}`,
19
+ );
20
+ }
21
+ }
18
22
  };
@@ -130,12 +130,35 @@ export class LangchainAgent {
130
130
  agentConfig.systemPrompt = `${agentConfig.systemPrompt ?? ""}\n\n${TODO_WRITE_INSTRUCTIONS}`;
131
131
  }
132
132
  const agent = createAgent(agentConfig);
133
- const messages = req.prompt
134
- .filter((promptMsg) => promptMsg.type === "text")
135
- .map((promptMsg) => ({
136
- type: "human",
137
- content: promptMsg.text,
138
- }));
133
+ // Build messages from session history if available, otherwise use just the prompt
134
+ let messages;
135
+ if (req.sessionMessages && req.sessionMessages.length > 0) {
136
+ // Use session message history - convert to LangChain format
137
+ // Only include messages BEFORE the current user message (exclude the last one since it's the current prompt)
138
+ const historyMessages = req.sessionMessages.slice(0, -1);
139
+ messages = historyMessages.map((msg) => ({
140
+ type: msg.role === "user" ? "human" : "ai",
141
+ content: msg.content,
142
+ }));
143
+ // Add the current prompt as the final human message
144
+ const currentPromptText = req.prompt
145
+ .filter((promptMsg) => promptMsg.type === "text")
146
+ .map((promptMsg) => promptMsg.text)
147
+ .join("\n");
148
+ messages.push({
149
+ type: "human",
150
+ content: currentPromptText,
151
+ });
152
+ }
153
+ else {
154
+ // Fallback: No session history, use just the prompt (legacy behavior)
155
+ messages = req.prompt
156
+ .filter((promptMsg) => promptMsg.type === "text")
157
+ .map((promptMsg) => ({
158
+ type: "human",
159
+ content: promptMsg.text,
160
+ }));
161
+ }
139
162
  const stream = agent.stream({ messages }, {
140
163
  streamMode: ["updates", "messages"],
141
164
  });
@@ -230,7 +253,7 @@ export class LangchainAgent {
230
253
  : typeof aiMessage.content === "string"
231
254
  ? aiMessage.content.length
232
255
  : -1;
233
- console.error("DEBUG agent: messageTokenUsage:", JSON.stringify(messageTokenUsage), "contentType:", contentType, "isArray:", contentIsArray, "length:", contentLength);
256
+ console.log("DEBUG agent: messageTokenUsage:", JSON.stringify(messageTokenUsage), "contentType:", contentType, "isArray:", contentIsArray, "length:", contentLength);
234
257
  }
235
258
  // If we have tokenUsage but no content, send a token-only chunk
236
259
  if (messageTokenUsage &&
@@ -238,7 +261,7 @@ export class LangchainAgent {
238
261
  ? aiMessage.content === ""
239
262
  : Array.isArray(aiMessage.content) &&
240
263
  aiMessage.content.length === 0)) {
241
- console.error("DEBUG agent: sending token-only chunk:", JSON.stringify(messageTokenUsage));
264
+ console.log("DEBUG agent: sending token-only chunk:", JSON.stringify(messageTokenUsage));
242
265
  const msgToYield = {
243
266
  sessionUpdate: "agent_message_chunk",
244
267
  content: {
@@ -271,7 +294,7 @@ export class LangchainAgent {
271
294
  text: aiMessage.content,
272
295
  },
273
296
  };
274
- console.error("DEBUG agent: yielding message (string content):", JSON.stringify(msgToYield));
297
+ console.log("DEBUG agent: yielding message (string content):", JSON.stringify(msgToYield));
275
298
  yield msgToYield;
276
299
  }
277
300
  else if (Array.isArray(aiMessage.content)) {
@@ -295,7 +318,7 @@ export class LangchainAgent {
295
318
  text: part.text,
296
319
  },
297
320
  };
298
- console.error("DEBUG agent: yielding message (array content):", JSON.stringify(msgToYield));
321
+ console.log("DEBUG agent: yielding message (array content):", JSON.stringify(msgToYield));
299
322
  yield msgToYield;
300
323
  }
301
324
  else if (part.type === "tool_use") {
@@ -50,14 +50,21 @@ export async function generateIndexTs(vars) {
50
50
  };
51
51
  return prettier.format(`import { makeHttpTransport, makeStdioTransport } from "@townco/agent/acp-server";
52
52
  import type { AgentDefinition } from "@townco/agent/definition";
53
+ import { basename } from "node:path";
53
54
 
54
55
  // Load agent definition from JSON file
55
56
  const agent: AgentDefinition = ${JSON.stringify(agentDef)};
56
57
 
57
58
  const transport = process.argv[2] || "stdio";
58
59
 
60
+ // Get agent directory and name for session storage
61
+ const agentDir = process.cwd();
62
+ const agentName = basename(agentDir);
63
+
64
+ console.log("[agent] Configuration:", { transport, agentDir, agentName });
65
+
59
66
  if (transport === "http") {
60
- makeHttpTransport(agent);
67
+ makeHttpTransport(agent, agentDir, agentName);
61
68
  } else if (transport === "stdio") {
62
69
  makeStdioTransport(agent);
63
70
  } else {
@@ -75,6 +82,7 @@ export function generateGitignore() {
75
82
  return `node_modules
76
83
  dist
77
84
  .env
85
+ .sessions
78
86
  `;
79
87
  }
80
88
  export function generateTsConfig() {