@townco/agent 0.1.117 → 0.1.118
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 +3 -3
- package/dist/acp-server/adapter.js +101 -79
- package/dist/acp-server/http.js +28 -1
- package/dist/acp-server/session-storage.d.ts +27 -1
- package/dist/acp-server/session-storage.js +19 -1
- package/dist/definition/index.d.ts +4 -1
- package/dist/definition/models.d.ts +6 -0
- package/dist/definition/models.js +1 -0
- package/dist/mcp/index.d.ts +12 -0
- package/dist/mcp/index.js +83 -0
- package/dist/runner/hooks/predefined/compaction-tool.js +13 -1
- package/dist/runner/hooks/predefined/mid-turn-compaction.js +13 -1
- package/dist/runner/hooks/types.d.ts +6 -0
- package/dist/runner/index.d.ts +2 -66
- package/dist/runner/langchain/index.js +4 -4
- package/dist/runner/langchain/tools/subagent-connections.d.ts +2 -0
- package/dist/runner/langchain/tools/subagent.js +230 -3
- package/dist/templates/index.js +16 -16
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +11 -7
- package/templates/index.ts +19 -19
package/dist/runner/index.d.ts
CHANGED
|
@@ -1,68 +1,4 @@
|
|
|
1
|
+
import type { AgentDefinition } from "../definition";
|
|
1
2
|
import { type AgentRunner, type SessionUpdateNotification } from "./agent-runner";
|
|
2
3
|
export type { AgentRunner, SessionUpdateNotification };
|
|
3
|
-
export declare const makeRunnerFromDefinition: (definition:
|
|
4
|
-
displayName?: string | undefined;
|
|
5
|
-
version?: string | undefined;
|
|
6
|
-
description?: string | undefined;
|
|
7
|
-
suggestedPrompts?: string[] | undefined;
|
|
8
|
-
systemPrompt: string | null;
|
|
9
|
-
model: string;
|
|
10
|
-
tools?: (string | {
|
|
11
|
-
type: "custom";
|
|
12
|
-
modulePath: string;
|
|
13
|
-
} | {
|
|
14
|
-
type: "filesystem";
|
|
15
|
-
working_directory?: string | undefined;
|
|
16
|
-
} | {
|
|
17
|
-
type: "direct";
|
|
18
|
-
name: string;
|
|
19
|
-
description: string;
|
|
20
|
-
fn: import("zod/v4/core").$InferOuterFunctionType<import("zod/v4/core").$ZodFunctionArgs, import("zod/v4/core").$ZodFunctionOut>;
|
|
21
|
-
schema: any;
|
|
22
|
-
prettyName?: string | undefined;
|
|
23
|
-
icon?: string | undefined;
|
|
24
|
-
})[] | undefined;
|
|
25
|
-
mcps?: (string | {
|
|
26
|
-
name: string;
|
|
27
|
-
transport: "stdio";
|
|
28
|
-
command: string;
|
|
29
|
-
args?: string[] | undefined;
|
|
30
|
-
} | {
|
|
31
|
-
name: string;
|
|
32
|
-
transport: "http";
|
|
33
|
-
url: string;
|
|
34
|
-
headers?: Record<string, string> | undefined;
|
|
35
|
-
})[] | undefined;
|
|
36
|
-
harnessImplementation?: "langchain" | undefined;
|
|
37
|
-
hooks?: {
|
|
38
|
-
type: "context_size" | "tool_response";
|
|
39
|
-
setting?: Record<string, unknown> | {
|
|
40
|
-
threshold: number;
|
|
41
|
-
} | {
|
|
42
|
-
maxTokensSize?: number | undefined;
|
|
43
|
-
} | undefined;
|
|
44
|
-
callback?: string | undefined;
|
|
45
|
-
callbacks?: {
|
|
46
|
-
name: string;
|
|
47
|
-
setting?: Record<string, unknown> | undefined;
|
|
48
|
-
}[] | undefined;
|
|
49
|
-
}[] | undefined;
|
|
50
|
-
initialMessage?: {
|
|
51
|
-
enabled: boolean;
|
|
52
|
-
content: string;
|
|
53
|
-
} | undefined;
|
|
54
|
-
uiConfig?: {
|
|
55
|
-
hideTopBar?: boolean | undefined;
|
|
56
|
-
} | undefined;
|
|
57
|
-
promptParameters?: {
|
|
58
|
-
id: string;
|
|
59
|
-
label: string;
|
|
60
|
-
description?: string | undefined;
|
|
61
|
-
options: {
|
|
62
|
-
id: string;
|
|
63
|
-
label: string;
|
|
64
|
-
systemPromptAddendum?: string | undefined;
|
|
65
|
-
}[];
|
|
66
|
-
defaultOptionId?: string | undefined;
|
|
67
|
-
}[] | undefined;
|
|
68
|
-
}) => AgentRunner;
|
|
4
|
+
export declare const makeRunnerFromDefinition: (definition: AgentDefinition) => AgentRunner;
|
|
@@ -892,7 +892,7 @@ export class LangchainAgent {
|
|
|
892
892
|
}
|
|
893
893
|
}
|
|
894
894
|
// Iterate through the merged stream
|
|
895
|
-
let
|
|
895
|
+
let _messageCount = 0;
|
|
896
896
|
for await (const item of mergeStreams()) {
|
|
897
897
|
if (item.source === "subagent") {
|
|
898
898
|
// Yield any queued subagent messages
|
|
@@ -901,7 +901,7 @@ export class LangchainAgent {
|
|
|
901
901
|
}
|
|
902
902
|
// Process the stream item
|
|
903
903
|
const streamItem = item.value;
|
|
904
|
-
|
|
904
|
+
_messageCount++;
|
|
905
905
|
// biome-ignore lint/suspicious/noExplicitAny: LangChain stream items are tuples with dynamic types
|
|
906
906
|
const [streamMode, chunk] = streamItem;
|
|
907
907
|
if (streamMode === "updates") {
|
|
@@ -1293,9 +1293,9 @@ export class LangchainAgent {
|
|
|
1293
1293
|
const maxWaitTime = 300000; // Absolute max 5 minutes
|
|
1294
1294
|
const startTime = Date.now();
|
|
1295
1295
|
let lastMessageTime = Date.now();
|
|
1296
|
-
let
|
|
1296
|
+
let _iterations = 0;
|
|
1297
1297
|
while (Date.now() - startTime < maxWaitTime) {
|
|
1298
|
-
|
|
1298
|
+
_iterations++;
|
|
1299
1299
|
// Check if there are pending messages
|
|
1300
1300
|
if (subagentMessagesQueue.length > 0) {
|
|
1301
1301
|
yield* yieldPendingSubagentUpdates();
|
|
@@ -7,6 +7,8 @@ export interface SubagentToolCall {
|
|
|
7
7
|
prettyName?: string | undefined;
|
|
8
8
|
icon?: string | undefined;
|
|
9
9
|
status: "pending" | "in_progress" | "completed" | "failed";
|
|
10
|
+
rawInput?: Record<string, unknown> | undefined;
|
|
11
|
+
rawOutput?: Record<string, unknown> | undefined;
|
|
10
12
|
}
|
|
11
13
|
/**
|
|
12
14
|
* Content block for sub-agent messages
|
|
@@ -10,6 +10,175 @@ import { makeRunnerFromDefinition } from "../../index.js";
|
|
|
10
10
|
import { bindGeneratorToSessionContext, getAbortSignal, } from "../../session-context.js";
|
|
11
11
|
import { emitSubagentMessages, hashQuery, } from "./subagent-connections.js";
|
|
12
12
|
const logger = createLogger("subagent-tool", "debug");
|
|
13
|
+
/**
|
|
14
|
+
* Helper to derive favicon URL from a domain
|
|
15
|
+
*/
|
|
16
|
+
function getFaviconUrl(url) {
|
|
17
|
+
try {
|
|
18
|
+
const domain = new URL(url).hostname;
|
|
19
|
+
return `https://www.google.com/s2/favicons?domain=${domain}&sz=32`;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Helper to get a human-readable source name from URL
|
|
27
|
+
*/
|
|
28
|
+
function getSourceName(url) {
|
|
29
|
+
try {
|
|
30
|
+
const hostname = new URL(url).hostname;
|
|
31
|
+
// Remove www. prefix and return domain name
|
|
32
|
+
return hostname.replace(/^www\./, "");
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Extract citation sources from a tool's raw output.
|
|
40
|
+
* This handles WebSearch, WebFetch, and library tools.
|
|
41
|
+
*
|
|
42
|
+
* Note: The runner wraps tool results as { content: JSON.stringify(result) },
|
|
43
|
+
* so we need to parse rawOutput.content if it's a string.
|
|
44
|
+
*/
|
|
45
|
+
function extractSourcesFromToolOutput(toolName, rawOutput, toolCallId, sourceCounter) {
|
|
46
|
+
const sources = [];
|
|
47
|
+
// Parse the actual output from the wrapper
|
|
48
|
+
// The runner wraps results as { content: JSON.stringify(actualResult) }
|
|
49
|
+
let actualOutput = rawOutput;
|
|
50
|
+
if (typeof rawOutput.content === "string") {
|
|
51
|
+
try {
|
|
52
|
+
const parsed = JSON.parse(rawOutput.content);
|
|
53
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
54
|
+
actualOutput = parsed;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Not valid JSON, use rawOutput as-is
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Handle WebSearch (Exa) results
|
|
62
|
+
if (toolName === "WebSearch" || toolName === "web_search") {
|
|
63
|
+
// Check for formatted results with citation IDs first
|
|
64
|
+
const formattedResults = actualOutput.formattedForCitation;
|
|
65
|
+
if (Array.isArray(formattedResults)) {
|
|
66
|
+
for (const result of formattedResults) {
|
|
67
|
+
if (result &&
|
|
68
|
+
typeof result === "object" &&
|
|
69
|
+
"url" in result &&
|
|
70
|
+
typeof result.url === "string") {
|
|
71
|
+
// Use the citationId from the tool output if available
|
|
72
|
+
const citationId = typeof result.citationId === "number"
|
|
73
|
+
? String(result.citationId)
|
|
74
|
+
: (() => {
|
|
75
|
+
sourceCounter.value++;
|
|
76
|
+
return String(sourceCounter.value);
|
|
77
|
+
})();
|
|
78
|
+
const url = result.url;
|
|
79
|
+
const title = typeof result.title === "string" ? result.title : "Untitled";
|
|
80
|
+
const snippet = typeof result.text === "string"
|
|
81
|
+
? result.text.slice(0, 200)
|
|
82
|
+
: undefined;
|
|
83
|
+
sources.push({
|
|
84
|
+
id: citationId,
|
|
85
|
+
url,
|
|
86
|
+
title,
|
|
87
|
+
snippet,
|
|
88
|
+
favicon: getFaviconUrl(url),
|
|
89
|
+
toolCallId,
|
|
90
|
+
sourceName: getSourceName(url),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
// Fallback to raw results (backwards compatibility)
|
|
97
|
+
const results = actualOutput.results;
|
|
98
|
+
if (Array.isArray(results)) {
|
|
99
|
+
for (const result of results) {
|
|
100
|
+
if (result &&
|
|
101
|
+
typeof result === "object" &&
|
|
102
|
+
"url" in result &&
|
|
103
|
+
typeof result.url === "string") {
|
|
104
|
+
sourceCounter.value++;
|
|
105
|
+
const url = result.url;
|
|
106
|
+
const title = typeof result.title === "string" ? result.title : "Untitled";
|
|
107
|
+
const snippet = typeof result.text === "string"
|
|
108
|
+
? result.text.slice(0, 200)
|
|
109
|
+
: undefined;
|
|
110
|
+
sources.push({
|
|
111
|
+
id: String(sourceCounter.value),
|
|
112
|
+
url,
|
|
113
|
+
title,
|
|
114
|
+
snippet,
|
|
115
|
+
favicon: getFaviconUrl(url),
|
|
116
|
+
toolCallId,
|
|
117
|
+
sourceName: getSourceName(url),
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Handle WebFetch - extract URLs from the fetched content
|
|
125
|
+
// Note: WebFetch returns plain text (the AI-processed result), not structured data
|
|
126
|
+
// So we skip URL extraction here as the URLs would be from the content itself
|
|
127
|
+
// The actual fetched URL should be tracked via tool input, not output
|
|
128
|
+
// Handle library/document retrieval tools
|
|
129
|
+
const isLibraryTool = toolName.startsWith("library__") ||
|
|
130
|
+
toolName.includes("get_document") ||
|
|
131
|
+
toolName.includes("retrieve_document") ||
|
|
132
|
+
toolName.includes("bibliotecha");
|
|
133
|
+
if (isLibraryTool) {
|
|
134
|
+
// Helper to extract a single document source
|
|
135
|
+
const extractDocSource = (doc) => {
|
|
136
|
+
const docUrl = typeof doc.document_url === "string"
|
|
137
|
+
? doc.document_url
|
|
138
|
+
: typeof doc.url === "string"
|
|
139
|
+
? doc.url
|
|
140
|
+
: typeof doc.source_url === "string"
|
|
141
|
+
? doc.source_url
|
|
142
|
+
: null;
|
|
143
|
+
const docTitle = typeof doc.title === "string" ? doc.title : null;
|
|
144
|
+
const docId = typeof doc.document_id === "number"
|
|
145
|
+
? String(doc.document_id)
|
|
146
|
+
: typeof doc.document_id === "string"
|
|
147
|
+
? doc.document_id
|
|
148
|
+
: null;
|
|
149
|
+
if (!docUrl && !docTitle) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
sourceCounter.value++;
|
|
153
|
+
return {
|
|
154
|
+
id: docId || String(sourceCounter.value),
|
|
155
|
+
url: docUrl || "",
|
|
156
|
+
title: docTitle || docUrl || "Document",
|
|
157
|
+
toolCallId,
|
|
158
|
+
...(docUrl && { favicon: getFaviconUrl(docUrl) }),
|
|
159
|
+
...(docUrl && { sourceName: getSourceName(docUrl) }),
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
|
+
// Extract from single document fields
|
|
163
|
+
const singleDoc = extractDocSource(actualOutput);
|
|
164
|
+
if (singleDoc) {
|
|
165
|
+
sources.push(singleDoc);
|
|
166
|
+
}
|
|
167
|
+
// Extract from documents array
|
|
168
|
+
const documents = actualOutput.documents;
|
|
169
|
+
if (Array.isArray(documents)) {
|
|
170
|
+
for (const doc of documents) {
|
|
171
|
+
if (doc && typeof doc === "object") {
|
|
172
|
+
const docSource = extractDocSource(doc);
|
|
173
|
+
if (docSource) {
|
|
174
|
+
sources.push(docSource);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return sources;
|
|
181
|
+
}
|
|
13
182
|
/**
|
|
14
183
|
* Name of the Task tool created by makeSubagentsTool
|
|
15
184
|
*/
|
|
@@ -211,6 +380,7 @@ async function querySubagent(agentName, agentPath, agentWorkingDirectory, query)
|
|
|
211
380
|
// Consume stream, accumulate results, and emit incremental updates
|
|
212
381
|
let responseText = "";
|
|
213
382
|
const collectedSources = [];
|
|
383
|
+
const sourceCounter = { value: 0 }; // Mutable counter for source ID generation
|
|
214
384
|
const currentMessage = {
|
|
215
385
|
id: `subagent-${Date.now()}`,
|
|
216
386
|
content: "",
|
|
@@ -218,6 +388,7 @@ async function querySubagent(agentName, agentPath, agentWorkingDirectory, query)
|
|
|
218
388
|
toolCalls: [],
|
|
219
389
|
};
|
|
220
390
|
const toolCallMap = new Map();
|
|
391
|
+
const toolNameMap = new Map(); // Map toolCallId -> toolName
|
|
221
392
|
const queryHash = hashQuery(query);
|
|
222
393
|
logger.info("[DEBUG] Starting subagent generator loop", {
|
|
223
394
|
agentName,
|
|
@@ -249,15 +420,23 @@ async function querySubagent(agentName, agentPath, agentWorkingDirectory, query)
|
|
|
249
420
|
// Handle tool_call
|
|
250
421
|
if (update.sessionUpdate === "tool_call" && update.toolCallId) {
|
|
251
422
|
const meta = update._meta;
|
|
423
|
+
// Extract rawInput from the update
|
|
424
|
+
const rawInput = update
|
|
425
|
+
.rawInput;
|
|
252
426
|
const toolCall = {
|
|
253
427
|
id: update.toolCallId,
|
|
254
428
|
title: update.title || "Tool call",
|
|
255
429
|
prettyName: meta?.prettyName,
|
|
256
430
|
icon: meta?.icon,
|
|
257
431
|
status: update.status || "pending",
|
|
432
|
+
rawInput,
|
|
258
433
|
};
|
|
259
434
|
currentMessage.toolCalls.push(toolCall);
|
|
260
435
|
toolCallMap.set(update.toolCallId, currentMessage.toolCalls.length - 1);
|
|
436
|
+
// Store tool name for source extraction when output arrives
|
|
437
|
+
if (update.title) {
|
|
438
|
+
toolNameMap.set(update.toolCallId, update.title);
|
|
439
|
+
}
|
|
261
440
|
currentMessage.contentBlocks.push({ type: "tool_call", toolCall });
|
|
262
441
|
shouldEmit = true; // Emit when new tool call appears
|
|
263
442
|
}
|
|
@@ -276,9 +455,41 @@ async function querySubagent(agentName, agentPath, agentWorkingDirectory, query)
|
|
|
276
455
|
shouldEmit = true; // Emit when tool status changes
|
|
277
456
|
}
|
|
278
457
|
}
|
|
458
|
+
// Handle tool_output - capture rawOutput and extract sources
|
|
459
|
+
// (rawOutput will be included in final emit when subagent completes)
|
|
460
|
+
if (update.sessionUpdate === "tool_output" && update.toolCallId) {
|
|
461
|
+
const outputUpdate = update;
|
|
462
|
+
const idx = toolCallMap.get(update.toolCallId);
|
|
463
|
+
if (idx !== undefined && currentMessage.toolCalls[idx]) {
|
|
464
|
+
if (outputUpdate.rawOutput) {
|
|
465
|
+
currentMessage.toolCalls[idx].rawOutput = outputUpdate.rawOutput;
|
|
466
|
+
// Also update the content block
|
|
467
|
+
const block = currentMessage.contentBlocks.find((b) => b.type === "tool_call" && b.toolCall.id === update.toolCallId);
|
|
468
|
+
if (block) {
|
|
469
|
+
block.toolCall.rawOutput = outputUpdate.rawOutput;
|
|
470
|
+
}
|
|
471
|
+
// Extract citation sources from tool output (WebSearch, WebFetch, library tools)
|
|
472
|
+
const toolName = toolNameMap.get(update.toolCallId) || "";
|
|
473
|
+
const extractedSources = extractSourcesFromToolOutput(toolName, outputUpdate.rawOutput, update.toolCallId, sourceCounter);
|
|
474
|
+
if (extractedSources.length > 0) {
|
|
475
|
+
collectedSources.push(...extractedSources);
|
|
476
|
+
logger.info("Extracted sources from subagent tool output", {
|
|
477
|
+
toolName,
|
|
478
|
+
toolCallId: update.toolCallId,
|
|
479
|
+
sourcesCount: extractedSources.length,
|
|
480
|
+
});
|
|
481
|
+
shouldEmit = true; // Emit when sources are extracted
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
// NOTE: Don't set shouldEmit for rawOutput alone - rawOutput is large and will be
|
|
485
|
+
// included in the final emit when the subagent completes
|
|
486
|
+
}
|
|
487
|
+
}
|
|
279
488
|
// Handle sources (from ACP protocol)
|
|
280
|
-
if ("sources" in update &&
|
|
281
|
-
|
|
489
|
+
if ("sources" in update &&
|
|
490
|
+
Array.isArray(update.sources)) {
|
|
491
|
+
const sources = update
|
|
492
|
+
.sources;
|
|
282
493
|
for (const source of sources) {
|
|
283
494
|
const citationSource = {
|
|
284
495
|
id: source.id,
|
|
@@ -305,7 +516,23 @@ async function querySubagent(agentName, agentPath, agentWorkingDirectory, query)
|
|
|
305
516
|
contentBlocksCount: currentMessage.contentBlocks.length,
|
|
306
517
|
toolCallsCount: currentMessage.toolCalls.length,
|
|
307
518
|
});
|
|
308
|
-
|
|
519
|
+
// Strip rawOutput from streamed messages to avoid OOM in browser
|
|
520
|
+
// rawOutput is preserved in currentMessage for final session save
|
|
521
|
+
const streamMessage = {
|
|
522
|
+
...currentMessage,
|
|
523
|
+
toolCalls: currentMessage.toolCalls.map((tc) => {
|
|
524
|
+
const { rawOutput: _rawOutput, ...rest } = tc;
|
|
525
|
+
return rest;
|
|
526
|
+
}),
|
|
527
|
+
contentBlocks: currentMessage.contentBlocks.map((block) => {
|
|
528
|
+
if (block.type === "tool_call") {
|
|
529
|
+
const { rawOutput: _rawOutput, ...rest } = block.toolCall;
|
|
530
|
+
return { type: "tool_call", toolCall: rest };
|
|
531
|
+
}
|
|
532
|
+
return block;
|
|
533
|
+
}),
|
|
534
|
+
};
|
|
535
|
+
emitSubagentMessages(queryHash, [streamMessage]);
|
|
309
536
|
}
|
|
310
537
|
}
|
|
311
538
|
logger.info("[DEBUG] Subagent generator loop finished", {
|
package/dist/templates/index.js
CHANGED
|
@@ -74,16 +74,21 @@ export async function generateIndexTs(vars) {
|
|
|
74
74
|
if (vars.hooks) {
|
|
75
75
|
agentDef.hooks = vars.hooks;
|
|
76
76
|
}
|
|
77
|
-
return prettier.format(`import {
|
|
78
|
-
import type { AgentDefinition } from "@townco/agent/definition";
|
|
79
|
-
import { createLogger } from "@townco/agent/logger";
|
|
80
|
-
import { basename } from "node:path";
|
|
81
|
-
|
|
82
|
-
const logger = createLogger("agent-index");
|
|
77
|
+
return prettier.format(`import type { AgentDefinition } from "@townco/agent/definition";
|
|
83
78
|
|
|
84
|
-
// Load agent definition from JSON file
|
|
85
79
|
const agent: AgentDefinition = ${JSON.stringify(agentDef)};
|
|
86
80
|
|
|
81
|
+
export default agent;
|
|
82
|
+
`, { parser: "typescript" });
|
|
83
|
+
}
|
|
84
|
+
export function generateBinTs() {
|
|
85
|
+
return `#!/usr/bin/env bun
|
|
86
|
+
import { basename } from "node:path";
|
|
87
|
+
import { makeHttpTransport, makeStdioTransport } from "@townco/agent/acp-server";
|
|
88
|
+
import { createLogger } from "@townco/agent/logger";
|
|
89
|
+
import agent from "./index";
|
|
90
|
+
|
|
91
|
+
const logger = createLogger("agent-index");
|
|
87
92
|
const transport = process.argv[2] || "stdio";
|
|
88
93
|
|
|
89
94
|
// Get agent directory and name for session storage
|
|
@@ -93,18 +98,13 @@ const agentName = basename(agentDir);
|
|
|
93
98
|
logger.info("Configuration", { transport, agentDir, agentName });
|
|
94
99
|
|
|
95
100
|
if (transport === "http") {
|
|
96
|
-
|
|
101
|
+
makeHttpTransport(agent, agentDir, agentName);
|
|
97
102
|
} else if (transport === "stdio") {
|
|
98
|
-
|
|
103
|
+
makeStdioTransport(agent);
|
|
99
104
|
} else {
|
|
100
|
-
|
|
101
|
-
|
|
105
|
+
logger.error(\`Invalid transport: \${transport}\`);
|
|
106
|
+
process.exit(1);
|
|
102
107
|
}
|
|
103
|
-
`, { parser: "typescript" });
|
|
104
|
-
}
|
|
105
|
-
export function generateBinTs() {
|
|
106
|
-
return `#!/usr/bin/env bun
|
|
107
|
-
import "./index.ts";
|
|
108
108
|
`;
|
|
109
109
|
}
|
|
110
110
|
export function generateGitignore() {
|