@townco/agent 0.1.22 → 0.1.24
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/acp-server/adapter.d.ts +10 -14
- package/dist/acp-server/cli.d.ts +1 -3
- package/dist/acp-server/cli.js +5 -9
- package/dist/acp-server/http.d.ts +1 -3
- package/dist/acp-server/http.js +2 -2
- package/dist/bin.js +0 -0
- package/dist/definition/index.d.ts +6 -0
- package/dist/definition/index.js +9 -0
- package/dist/index.js +11 -5
- package/dist/runner/agent-runner.d.ts +6 -0
- package/dist/runner/index.d.ts +1 -3
- package/dist/runner/index.js +14 -18
- package/dist/runner/langchain/index.js +35 -23
- package/dist/runner/langchain/tools/todo.d.ts +32 -48
- package/dist/runner/langchain/tools/web_search.d.ts +1 -1
- package/dist/runner/tools.d.ts +16 -0
- package/dist/runner/tools.js +10 -1
- package/dist/scaffold/claude-scaffold.d.ts +8 -0
- package/dist/scaffold/claude-scaffold.js +58 -0
- package/dist/scaffold/copy-gui.js +7 -81
- package/dist/scaffold/copy-tui.js +1 -65
- package/dist/scaffold/index.d.ts +3 -0
- package/dist/scaffold/index.js +27 -31
- package/dist/scaffold/project-scaffold.d.ts +12 -0
- package/dist/scaffold/project-scaffold.js +317 -0
- package/dist/scaffold/templates/dot-claude/CLAUDE-append.md +71 -0
- package/dist/storage/index.d.ts +5 -0
- package/dist/storage/index.js +60 -24
- package/dist/templates/index.d.ts +7 -2
- package/dist/templates/index.js +13 -16
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/tool.d.ts +36 -0
- package/dist/utils/tool.js +33 -0
- package/index.ts +11 -7
- package/package.json +7 -6
- package/templates/index.ts +23 -18
- package/dist/definition/mcp.d.ts +0 -0
- package/dist/definition/mcp.js +0 -0
- package/dist/definition/tools/todo.d.ts +0 -49
- package/dist/definition/tools/todo.js +0 -80
- package/dist/definition/tools/web_search.d.ts +0 -4
- package/dist/definition/tools/web_search.js +0 -26
- package/dist/dev-agent/index.d.ts +0 -2
- package/dist/dev-agent/index.js +0 -18
- package/dist/example.d.ts +0 -2
- package/dist/example.js +0 -19
|
@@ -2,18 +2,14 @@ import * as acp from "@agentclientprotocol/sdk";
|
|
|
2
2
|
import type { AgentRunner } from "../runner";
|
|
3
3
|
/** Adapts an Agent to speak the ACP protocol */
|
|
4
4
|
export declare class AgentAcpAdapter implements acp.Agent {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
_params: acp.SetSessionModeRequest,
|
|
16
|
-
): Promise<acp.SetSessionModeResponse>;
|
|
17
|
-
prompt(params: acp.PromptRequest): Promise<acp.PromptResponse>;
|
|
18
|
-
cancel(params: acp.CancelNotification): Promise<void>;
|
|
5
|
+
private connection;
|
|
6
|
+
private sessions;
|
|
7
|
+
private agent;
|
|
8
|
+
constructor(agent: AgentRunner, connection: acp.AgentSideConnection);
|
|
9
|
+
initialize(_params: acp.InitializeRequest): Promise<acp.InitializeResponse>;
|
|
10
|
+
newSession(_params: acp.NewSessionRequest): Promise<acp.NewSessionResponse>;
|
|
11
|
+
authenticate(_params: acp.AuthenticateRequest): Promise<acp.AuthenticateResponse | undefined>;
|
|
12
|
+
setSessionMode(_params: acp.SetSessionModeRequest): Promise<acp.SetSessionModeResponse>;
|
|
13
|
+
prompt(params: acp.PromptRequest): Promise<acp.PromptResponse>;
|
|
14
|
+
cancel(params: acp.CancelNotification): Promise<void>;
|
|
19
15
|
}
|
package/dist/acp-server/cli.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
import type { AgentDefinition } from "../definition";
|
|
2
2
|
import { type AgentRunner } from "../runner";
|
|
3
|
-
export declare function makeStdioTransport(
|
|
4
|
-
agent: AgentRunner | AgentDefinition,
|
|
5
|
-
): void;
|
|
3
|
+
export declare function makeStdioTransport(agent: AgentRunner | AgentDefinition): void;
|
package/dist/acp-server/cli.js
CHANGED
|
@@ -3,13 +3,9 @@ import * as acp from "@agentclientprotocol/sdk";
|
|
|
3
3
|
import { makeRunnerFromDefinition } from "../runner";
|
|
4
4
|
import { AgentAcpAdapter } from "./adapter";
|
|
5
5
|
export function makeStdioTransport(agent) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
new acp.AgentSideConnection(
|
|
12
|
-
(conn) => new AgentAcpAdapter(agentRunner, conn),
|
|
13
|
-
stream,
|
|
14
|
-
);
|
|
6
|
+
const agentRunner = "definition" in agent ? agent : makeRunnerFromDefinition(agent);
|
|
7
|
+
const input = Writable.toWeb(process.stdout);
|
|
8
|
+
const output = Readable.toWeb(process.stdin);
|
|
9
|
+
const stream = acp.ndJsonStream(input, output);
|
|
10
|
+
new acp.AgentSideConnection((conn) => new AgentAcpAdapter(agentRunner, conn), stream);
|
|
15
11
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
import type { AgentDefinition } from "../definition";
|
|
2
2
|
import { type AgentRunner } from "../runner";
|
|
3
|
-
export declare function makeHttpTransport(
|
|
4
|
-
agent: AgentRunner | AgentDefinition,
|
|
5
|
-
): void;
|
|
3
|
+
export declare function makeHttpTransport(agent: AgentRunner | AgentDefinition): void;
|
package/dist/acp-server/http.js
CHANGED
|
@@ -384,8 +384,8 @@ export function makeHttpTransport(agent) {
|
|
|
384
384
|
const writer = inbound.writable.getWriter();
|
|
385
385
|
await writer.write(encoder.encode(`${JSON.stringify(body)}\n`));
|
|
386
386
|
writer.releaseLock();
|
|
387
|
-
// Wait for response with
|
|
388
|
-
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Request timeout")),
|
|
387
|
+
// Wait for response with ten minute timeout
|
|
388
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Request timeout")), 10 * 60 * 1000));
|
|
389
389
|
try {
|
|
390
390
|
const response = await Promise.race([responsePromise, timeoutPromise]);
|
|
391
391
|
logger.debug("POST /rpc - Response received", { id });
|
package/dist/bin.js
CHANGED
|
File without changes
|
|
@@ -22,6 +22,12 @@ export declare const AgentDefinitionSchema: z.ZodObject<{
|
|
|
22
22
|
}, z.core.$strip>, z.ZodObject<{
|
|
23
23
|
type: z.ZodLiteral<"filesystem">;
|
|
24
24
|
working_directory: z.ZodOptional<z.ZodString>;
|
|
25
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
26
|
+
type: z.ZodLiteral<"direct">;
|
|
27
|
+
name: z.ZodString;
|
|
28
|
+
description: z.ZodString;
|
|
29
|
+
fn: z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>;
|
|
30
|
+
schema: z.ZodAny;
|
|
25
31
|
}, z.core.$strip>]>>>;
|
|
26
32
|
mcps: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
27
33
|
name: z.ZodString;
|
package/dist/definition/index.js
CHANGED
|
@@ -35,11 +35,20 @@ const FilesystemToolSchema = z.object({
|
|
|
35
35
|
/** If omitted, defaults to process.cwd() at runtime */
|
|
36
36
|
working_directory: z.string().optional(),
|
|
37
37
|
});
|
|
38
|
+
/** Direct tool configuration schema (for tools imported directly in code). */
|
|
39
|
+
const DirectToolSchema = z.object({
|
|
40
|
+
type: z.literal("direct"),
|
|
41
|
+
name: z.string(),
|
|
42
|
+
description: z.string(),
|
|
43
|
+
fn: z.function(),
|
|
44
|
+
schema: z.any(), // Accept any Zod schema
|
|
45
|
+
});
|
|
38
46
|
/** Tool schema - can be a string (built-in tool) or custom tool object. */
|
|
39
47
|
const ToolSchema = z.union([
|
|
40
48
|
z.string(),
|
|
41
49
|
CustomToolSchema,
|
|
42
50
|
FilesystemToolSchema,
|
|
51
|
+
DirectToolSchema,
|
|
43
52
|
]);
|
|
44
53
|
/** Agent definition schema. */
|
|
45
54
|
export const AgentDefinitionSchema = z.object({
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
1
|
import { makeHttpTransport, makeStdioTransport } from "./acp-server";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
const exampleAgent = {
|
|
3
|
+
model: "claude-sonnet-4-5-20250929",
|
|
4
|
+
systemPrompt: "You are a helpful assistant.",
|
|
5
|
+
tools: [
|
|
6
|
+
"todo_write",
|
|
7
|
+
"get_weather",
|
|
8
|
+
"web_search",
|
|
9
|
+
{ type: "filesystem", working_directory: "/Users/michael/code/town" },
|
|
10
|
+
],
|
|
11
|
+
mcps: [],
|
|
12
|
+
};
|
|
7
13
|
// Parse transport type from command line argument
|
|
8
14
|
const transport = process.argv[2] || "stdio";
|
|
9
15
|
if (transport === "http") {
|
|
@@ -9,6 +9,12 @@ export declare const zAgentRunnerParams: z.ZodObject<{
|
|
|
9
9
|
}, z.core.$strip>, z.ZodObject<{
|
|
10
10
|
type: z.ZodLiteral<"filesystem">;
|
|
11
11
|
working_directory: z.ZodOptional<z.ZodString>;
|
|
12
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
13
|
+
type: z.ZodLiteral<"direct">;
|
|
14
|
+
name: z.ZodString;
|
|
15
|
+
description: z.ZodString;
|
|
16
|
+
fn: z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>;
|
|
17
|
+
schema: z.ZodAny;
|
|
12
18
|
}, z.core.$strip>]>>>;
|
|
13
19
|
mcps: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
14
20
|
name: z.ZodString;
|
package/dist/runner/index.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
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: (
|
|
5
|
-
definition: AgentDefinition,
|
|
6
|
-
) => AgentRunner;
|
|
4
|
+
export declare const makeRunnerFromDefinition: (definition: AgentDefinition) => AgentRunner;
|
package/dist/runner/index.js
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
import { zAgentRunnerParams } from "./agent-runner";
|
|
2
2
|
import { LangchainAgent } from "./langchain";
|
|
3
3
|
export const makeRunnerFromDefinition = (definition) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
`Unsupported harness implementation: ${definition.harnessImplementation}`,
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
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
|
+
}
|
|
22
18
|
};
|
|
@@ -73,6 +73,16 @@ export class LangchainAgent {
|
|
|
73
73
|
process.cwd();
|
|
74
74
|
enabledTools.push(...makeFilesystemTools(wd));
|
|
75
75
|
}
|
|
76
|
+
else if (type === "direct") {
|
|
77
|
+
// Handle direct tool objects (imported in code)
|
|
78
|
+
// biome-ignore lint/suspicious/noExplicitAny: mlai unsure how to best type this
|
|
79
|
+
const addedTool = tool(t.fn, {
|
|
80
|
+
name: t.name,
|
|
81
|
+
description: t.description,
|
|
82
|
+
schema: t.schema,
|
|
83
|
+
});
|
|
84
|
+
enabledTools.push(addedTool);
|
|
85
|
+
}
|
|
76
86
|
}
|
|
77
87
|
}
|
|
78
88
|
// Built-in tools from registry
|
|
@@ -147,30 +157,32 @@ export class LangchainAgent {
|
|
|
147
157
|
if (toolCall.id == null) {
|
|
148
158
|
throw new Error(`Tool call is missing id: ${JSON.stringify(toolCall)}`);
|
|
149
159
|
}
|
|
160
|
+
// TODO: re-add this suppression of the todo_write tool call when we
|
|
161
|
+
// are rendering the agent-plan update in the UIs
|
|
150
162
|
// If this is a todo_write tool call, yield an agent-plan update
|
|
151
|
-
if (toolCall.name === "todo_write" && toolCall.args?.todos) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
163
|
+
//if (toolCall.name === "todo_write" && toolCall.args?.todos) {
|
|
164
|
+
// const entries = toolCall.args.todos.flatMap((todo: unknown) => {
|
|
165
|
+
// const validation = todoItemSchema.safeParse(todo);
|
|
166
|
+
// if (!validation.success) {
|
|
167
|
+
// // Invalid todo - filter it out
|
|
168
|
+
// return [];
|
|
169
|
+
// }
|
|
170
|
+
// return [
|
|
171
|
+
// {
|
|
172
|
+
// content: validation.data.content,
|
|
173
|
+
// status: validation.data.status,
|
|
174
|
+
// priority: "medium" as const,
|
|
175
|
+
// },
|
|
176
|
+
// ];
|
|
177
|
+
// });
|
|
178
|
+
// yield {
|
|
179
|
+
// sessionUpdate: "plan",
|
|
180
|
+
// entries: entries,
|
|
181
|
+
// };
|
|
182
|
+
// // Track this tool call ID to suppress tool_call notifications
|
|
183
|
+
// todoWriteToolCallIds.add(toolCall.id);
|
|
184
|
+
// continue;
|
|
185
|
+
//}
|
|
174
186
|
yield {
|
|
175
187
|
sessionUpdate: "tool_call",
|
|
176
188
|
toolCallId: toolCall.id,
|
|
@@ -1,49 +1,33 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
export declare const todoItemSchema: z.ZodObject<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
{
|
|
35
|
-
todos: {
|
|
36
|
-
content: string;
|
|
37
|
-
status: "pending" | "in_progress" | "completed";
|
|
38
|
-
activeForm: string;
|
|
39
|
-
}[];
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
todos: {
|
|
43
|
-
content: string;
|
|
44
|
-
status: "pending" | "in_progress" | "completed";
|
|
45
|
-
activeForm: string;
|
|
46
|
-
}[];
|
|
47
|
-
},
|
|
48
|
-
string
|
|
49
|
-
>;
|
|
2
|
+
export declare const todoItemSchema: z.ZodObject<{
|
|
3
|
+
content: z.ZodString;
|
|
4
|
+
status: z.ZodEnum<{
|
|
5
|
+
pending: "pending";
|
|
6
|
+
in_progress: "in_progress";
|
|
7
|
+
completed: "completed";
|
|
8
|
+
}>;
|
|
9
|
+
activeForm: z.ZodString;
|
|
10
|
+
}, z.core.$strip>;
|
|
11
|
+
export declare const todoWrite: import("langchain").DynamicStructuredTool<z.ZodObject<{
|
|
12
|
+
todos: z.ZodArray<z.ZodObject<{
|
|
13
|
+
content: z.ZodString;
|
|
14
|
+
status: z.ZodEnum<{
|
|
15
|
+
pending: "pending";
|
|
16
|
+
in_progress: "in_progress";
|
|
17
|
+
completed: "completed";
|
|
18
|
+
}>;
|
|
19
|
+
activeForm: z.ZodString;
|
|
20
|
+
}, z.core.$strip>>;
|
|
21
|
+
}, z.core.$strip>, {
|
|
22
|
+
todos: {
|
|
23
|
+
content: string;
|
|
24
|
+
status: "pending" | "in_progress" | "completed";
|
|
25
|
+
activeForm: string;
|
|
26
|
+
}[];
|
|
27
|
+
}, {
|
|
28
|
+
todos: {
|
|
29
|
+
content: string;
|
|
30
|
+
status: "pending" | "in_progress" | "completed";
|
|
31
|
+
activeForm: string;
|
|
32
|
+
}[];
|
|
33
|
+
}, string>;
|
package/dist/runner/tools.d.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
/** Built-in tool types. */
|
|
3
3
|
export declare const zBuiltInToolType: z.ZodUnion<readonly [z.ZodLiteral<"todo_write">, z.ZodLiteral<"get_weather">, z.ZodLiteral<"web_search">, z.ZodLiteral<"filesystem">]>;
|
|
4
|
+
/** Direct tool object schema (for tools imported directly in code). */
|
|
5
|
+
declare const zDirectTool: z.ZodObject<{
|
|
6
|
+
type: z.ZodLiteral<"direct">;
|
|
7
|
+
name: z.ZodString;
|
|
8
|
+
description: z.ZodString;
|
|
9
|
+
fn: z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>;
|
|
10
|
+
schema: z.ZodAny;
|
|
11
|
+
}, z.core.$strip>;
|
|
4
12
|
/** Tool type - can be a built-in tool string or custom tool object. */
|
|
5
13
|
export declare const zToolType: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"todo_write">, z.ZodLiteral<"get_weather">, z.ZodLiteral<"web_search">, z.ZodLiteral<"filesystem">]>, z.ZodObject<{
|
|
6
14
|
type: z.ZodLiteral<"custom">;
|
|
@@ -8,6 +16,14 @@ export declare const zToolType: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodL
|
|
|
8
16
|
}, z.core.$strip>, z.ZodObject<{
|
|
9
17
|
type: z.ZodLiteral<"filesystem">;
|
|
10
18
|
working_directory: z.ZodOptional<z.ZodString>;
|
|
19
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
20
|
+
type: z.ZodLiteral<"direct">;
|
|
21
|
+
name: z.ZodString;
|
|
22
|
+
description: z.ZodString;
|
|
23
|
+
fn: z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>;
|
|
24
|
+
schema: z.ZodAny;
|
|
11
25
|
}, z.core.$strip>]>;
|
|
12
26
|
export type ToolType = z.infer<typeof zToolType>;
|
|
13
27
|
export type BuiltInToolType = z.infer<typeof zBuiltInToolType>;
|
|
28
|
+
export type DirectTool = z.infer<typeof zDirectTool>;
|
|
29
|
+
export {};
|
package/dist/runner/tools.js
CHANGED
|
@@ -6,7 +6,7 @@ export const zBuiltInToolType = z.union([
|
|
|
6
6
|
z.literal("web_search"),
|
|
7
7
|
z.literal("filesystem"),
|
|
8
8
|
]);
|
|
9
|
-
/** Custom tool schema. */
|
|
9
|
+
/** Custom tool schema (loaded from module path). */
|
|
10
10
|
const zCustomTool = z.object({
|
|
11
11
|
type: z.literal("custom"),
|
|
12
12
|
modulePath: z.string(),
|
|
@@ -16,9 +16,18 @@ const zFilesystemTool = z.object({
|
|
|
16
16
|
type: z.literal("filesystem"),
|
|
17
17
|
working_directory: z.string().optional(),
|
|
18
18
|
});
|
|
19
|
+
/** Direct tool object schema (for tools imported directly in code). */
|
|
20
|
+
const zDirectTool = z.object({
|
|
21
|
+
type: z.literal("direct"),
|
|
22
|
+
name: z.string(),
|
|
23
|
+
description: z.string(),
|
|
24
|
+
fn: z.function(),
|
|
25
|
+
schema: z.any(), // Accept any Zod schema
|
|
26
|
+
});
|
|
19
27
|
/** Tool type - can be a built-in tool string or custom tool object. */
|
|
20
28
|
export const zToolType = z.union([
|
|
21
29
|
zBuiltInToolType,
|
|
22
30
|
zCustomTool,
|
|
23
31
|
zFilesystemTool,
|
|
32
|
+
zDirectTool,
|
|
24
33
|
]);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Initialize Claude Code workspace integration by creating AGENTS.town.md
|
|
3
|
+
* and adding references to it in CLAUDE.md and AGENTS.md.
|
|
4
|
+
*
|
|
5
|
+
* @param targetPath - The root directory of the Town project
|
|
6
|
+
* @throws Error if target path doesn't exist
|
|
7
|
+
*/
|
|
8
|
+
export declare function initForClaudeCode(targetPath: string): Promise<void>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { appendFile, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
/**
|
|
8
|
+
* Initialize Claude Code workspace integration by creating AGENTS.town.md
|
|
9
|
+
* and adding references to it in CLAUDE.md and AGENTS.md.
|
|
10
|
+
*
|
|
11
|
+
* @param targetPath - The root directory of the Town project
|
|
12
|
+
* @throws Error if target path doesn't exist
|
|
13
|
+
*/
|
|
14
|
+
export async function initForClaudeCode(targetPath) {
|
|
15
|
+
// Verify target path exists
|
|
16
|
+
if (!existsSync(targetPath)) {
|
|
17
|
+
throw new Error(`Target path does not exist: ${targetPath}`);
|
|
18
|
+
}
|
|
19
|
+
// Source template directory (dot-claude in the scaffold package)
|
|
20
|
+
const templateDir = join(__dirname, "templates", "dot-claude");
|
|
21
|
+
const appendTemplatePath = join(templateDir, "CLAUDE-append.md");
|
|
22
|
+
if (!existsSync(appendTemplatePath)) {
|
|
23
|
+
throw new Error(`Claude template not found: ${appendTemplatePath}. This is a bug in the Town CLI.`);
|
|
24
|
+
}
|
|
25
|
+
// Handle AGENTS.town.md and references
|
|
26
|
+
const claudeMdPath = join(targetPath, "CLAUDE.md");
|
|
27
|
+
const agentsMdPath = join(targetPath, "AGENTS.md");
|
|
28
|
+
const agentsTownMdPath = join(targetPath, "AGENTS.town.md");
|
|
29
|
+
const townContent = await readFile(appendTemplatePath, "utf-8");
|
|
30
|
+
// Create AGENTS.town.md with the Town-specific content
|
|
31
|
+
await writeFile(agentsTownMdPath, townContent, "utf-8");
|
|
32
|
+
console.log("✓ Created AGENTS.town.md");
|
|
33
|
+
// Add reference to AGENTS.town.md in both CLAUDE.md and AGENTS.md
|
|
34
|
+
const referenceText = "\n\nThis repo uses the Town agent SDK -- please reference @AGENTS.town.md for more information\n";
|
|
35
|
+
// Handle CLAUDE.md
|
|
36
|
+
if (existsSync(claudeMdPath)) {
|
|
37
|
+
// CLAUDE.md exists, append reference
|
|
38
|
+
await appendFile(claudeMdPath, referenceText);
|
|
39
|
+
console.log("✓ Added Town SDK reference to CLAUDE.md");
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
// CLAUDE.md doesn't exist, create it with just the reference
|
|
43
|
+
await writeFile(claudeMdPath, `${referenceText.trim()}\n`, "utf-8");
|
|
44
|
+
console.log("✓ Created CLAUDE.md with Town SDK reference");
|
|
45
|
+
}
|
|
46
|
+
// Handle AGENTS.md
|
|
47
|
+
if (existsSync(agentsMdPath)) {
|
|
48
|
+
// AGENTS.md exists, append reference
|
|
49
|
+
await appendFile(agentsMdPath, referenceText);
|
|
50
|
+
console.log("✓ Added Town SDK reference to AGENTS.md");
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// AGENTS.md doesn't exist, create it with just the reference
|
|
54
|
+
await writeFile(agentsMdPath, `${referenceText.trim()}\n`, "utf-8");
|
|
55
|
+
console.log("✓ Created AGENTS.md with Town SDK reference");
|
|
56
|
+
}
|
|
57
|
+
console.log("✓ Claude Code workspace initialized");
|
|
58
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { cp, mkdir, writeFile } from "node:fs/promises";
|
|
1
|
+
import { cp, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
const require = createRequire(import.meta.url);
|
|
@@ -34,84 +34,10 @@ export async function copyGuiApp(agentPath) {
|
|
|
34
34
|
const targetPath = join(guiDir, item);
|
|
35
35
|
await cp(sourcePath, targetPath, { recursive: true });
|
|
36
36
|
}
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
declaration: true,
|
|
44
|
-
emitDecoratorMetadata: true,
|
|
45
|
-
esModuleInterop: true,
|
|
46
|
-
exactOptionalPropertyTypes: true,
|
|
47
|
-
experimentalDecorators: true,
|
|
48
|
-
jsx: "react-jsx",
|
|
49
|
-
lib: ["DOM", "ESNext"],
|
|
50
|
-
module: "ESNext",
|
|
51
|
-
moduleResolution: "bundler",
|
|
52
|
-
noFallthroughCasesInSwitch: true,
|
|
53
|
-
noImplicitAny: true,
|
|
54
|
-
noImplicitOverride: true,
|
|
55
|
-
noImplicitReturns: true,
|
|
56
|
-
noUncheckedIndexedAccess: true,
|
|
57
|
-
noUncheckedSideEffectImports: true,
|
|
58
|
-
noUnusedLocals: false,
|
|
59
|
-
noUnusedParameters: true,
|
|
60
|
-
resolveJsonModule: true,
|
|
61
|
-
skipLibCheck: true,
|
|
62
|
-
strict: true,
|
|
63
|
-
stripInternal: true,
|
|
64
|
-
target: "ESNext",
|
|
65
|
-
verbatimModuleSyntax: true,
|
|
66
|
-
outDir: "./dist",
|
|
67
|
-
rootDir: "./src",
|
|
68
|
-
},
|
|
69
|
-
include: ["src/**/*"],
|
|
70
|
-
exclude: ["node_modules", "dist"],
|
|
71
|
-
};
|
|
72
|
-
await writeFile(join(guiDir, "tsconfig.json"), JSON.stringify(guiTsConfig, null, 2));
|
|
73
|
-
// Generate a custom package.json for the GUI
|
|
74
|
-
// Use @townco/ui as a dependency instead of copying files
|
|
75
|
-
const packageJson = {
|
|
76
|
-
name: "agent-gui",
|
|
77
|
-
version: "0.0.1",
|
|
78
|
-
type: "module",
|
|
79
|
-
private: true,
|
|
80
|
-
scripts: {
|
|
81
|
-
dev: "vite",
|
|
82
|
-
build: "vite build",
|
|
83
|
-
preview: "vite preview",
|
|
84
|
-
},
|
|
85
|
-
dependencies: {
|
|
86
|
-
"@townco/ui": "^0.1.0",
|
|
87
|
-
"@agentclientprotocol/sdk": "^0.5.1",
|
|
88
|
-
"@radix-ui/react-dialog": "^1.1.15",
|
|
89
|
-
"@radix-ui/react-label": "^2.1.8",
|
|
90
|
-
"@radix-ui/react-select": "^2.2.6",
|
|
91
|
-
"@radix-ui/react-slot": "^1.2.4",
|
|
92
|
-
"@radix-ui/react-tabs": "^1.1.13",
|
|
93
|
-
"class-variance-authority": "^0.7.1",
|
|
94
|
-
clsx: "^2.1.1",
|
|
95
|
-
"lucide-react": "^0.552.0",
|
|
96
|
-
react: "^19.2.0",
|
|
97
|
-
"react-dom": "^19.2.0",
|
|
98
|
-
"react-markdown": "^10.1.0",
|
|
99
|
-
"remark-gfm": "^4.0.1",
|
|
100
|
-
"tailwind-merge": "^3.3.1",
|
|
101
|
-
zod: "^4.1.12",
|
|
102
|
-
zustand: "^5.0.8",
|
|
103
|
-
},
|
|
104
|
-
devDependencies: {
|
|
105
|
-
"@tailwindcss/postcss": "^4.1.17",
|
|
106
|
-
"@types/react": "^19.2.2",
|
|
107
|
-
"@types/react-dom": "^19.2.2",
|
|
108
|
-
"@vitejs/plugin-react": "^5.1.0",
|
|
109
|
-
autoprefixer: "^10.4.21",
|
|
110
|
-
postcss: "^8.5.6",
|
|
111
|
-
tailwindcss: "^4.1.17",
|
|
112
|
-
typescript: "^5.9.3",
|
|
113
|
-
vite: "^7.2.1",
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
await writeFile(join(guiDir, "package.json"), JSON.stringify(packageJson, null, 2));
|
|
37
|
+
// Fix the @source path in index.css to point to the correct node_modules location
|
|
38
|
+
// In agent projects, node_modules is at the project root (4 levels up from gui/src/)
|
|
39
|
+
const indexCssPath = join(guiDir, "src", "index.css");
|
|
40
|
+
const indexCssContent = await readFile(indexCssPath, "utf-8");
|
|
41
|
+
const updatedContent = indexCssContent.replace('@source "../node_modules/@townco/ui/dist/**/*.{js,d.ts}";', '@source "../../../../node_modules/@townco/ui/dist/**/*.{js,d.ts}";');
|
|
42
|
+
await writeFile(indexCssPath, updatedContent, "utf-8");
|
|
117
43
|
}
|