@townco/cli 0.1.82 → 0.1.84
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/commands/batch-wrapper.d.ts +26 -0
- package/dist/commands/batch-wrapper.js +35 -0
- package/dist/commands/batch.js +2 -2
- package/dist/commands/create-wrapper.d.ts +29 -0
- package/dist/commands/create-wrapper.js +92 -0
- package/dist/commands/create.js +39 -13
- package/dist/commands/deploy.d.ts +17 -0
- package/dist/commands/deploy.js +89 -0
- package/dist/commands/login.js +1 -1
- package/dist/commands/run-wrapper.d.ts +32 -0
- package/dist/commands/run-wrapper.js +32 -0
- package/dist/commands/run.js +23 -16
- package/dist/commands/secret.d.ts +62 -0
- package/dist/commands/secret.js +119 -0
- package/dist/components/LogsPane.d.ts +1 -1
- package/dist/components/LogsPane.js +12 -3
- package/dist/components/ProcessPane.d.ts +1 -1
- package/dist/components/ProcessPane.js +9 -1
- package/dist/components/StatusLine.js +4 -1
- package/dist/components/TabbedOutput.d.ts +1 -1
- package/dist/components/TabbedOutput.js +2 -1
- package/dist/index.js +21 -338
- package/dist/lib/command.d.ts +8 -0
- package/dist/lib/command.js +1 -0
- package/package.json +11 -15
package/dist/index.js
CHANGED
|
@@ -1,111 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import
|
|
3
|
-
import afs from "node:fs/promises";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import { argument, command, constant, flag, multiple, object, option, optional, or, } from "@optique/core";
|
|
2
|
+
import { command, constant, or } from "@optique/core";
|
|
6
3
|
import { message } from "@optique/core/message";
|
|
7
|
-
import { integer, string } from "@optique/core/valueparser";
|
|
8
4
|
import { run } from "@optique/run";
|
|
9
|
-
import { initForClaudeCode } from "@townco/agent/scaffold";
|
|
10
|
-
import { isInsideTownProject } from "@townco/agent/storage";
|
|
11
|
-
import { findRoot } from "@townco/core";
|
|
12
|
-
import { updateSchema as updateEnvSchema } from "@townco/env/update-schema";
|
|
13
|
-
import { createSecret, deleteSecret, genenv, listSecrets, updateSecret, } from "@townco/secret";
|
|
14
|
-
import { createTRPCClient, httpLink, httpSubscriptionLink, splitLink, } from "@trpc/client";
|
|
15
|
-
import archiver from "archiver";
|
|
16
|
-
import { EventSource } from "eventsource";
|
|
17
|
-
import walk from "ignore-walk";
|
|
18
|
-
import inquirer from "inquirer";
|
|
19
|
-
import superjson from "superjson";
|
|
20
5
|
import { match } from "ts-pattern";
|
|
21
|
-
import
|
|
22
|
-
import { configureCommand } from "
|
|
23
|
-
import
|
|
24
|
-
import
|
|
25
|
-
import { loginCommand } from "
|
|
26
|
-
import
|
|
27
|
-
import
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
|
|
31
|
-
* Securely prompt for a secret value without echoing to the terminal
|
|
32
|
-
*/
|
|
33
|
-
const promptSecret = async (secretName) => {
|
|
34
|
-
const answers = await inquirer.prompt([
|
|
35
|
-
{
|
|
36
|
-
type: "password",
|
|
37
|
-
name: "value",
|
|
38
|
-
message: `Enter value for secret '${secretName}':`,
|
|
39
|
-
mask: "*",
|
|
40
|
-
},
|
|
41
|
-
]);
|
|
42
|
-
return answers.value;
|
|
43
|
-
};
|
|
44
|
-
const parser = or(command("deploy", object({
|
|
45
|
-
command: constant("deploy"),
|
|
46
|
-
agent: option("-a", "--agent", string()),
|
|
47
|
-
}), {
|
|
48
|
-
brief: message `Deploy agents.`,
|
|
49
|
-
description: message `Deploy agents to the Town cloud.`,
|
|
50
|
-
}), command("configure", constant("configure"), {
|
|
6
|
+
import batchCmd from "@/commands/batch-wrapper";
|
|
7
|
+
import { configureCommand } from "@/commands/configure";
|
|
8
|
+
import createCmd from "@/commands/create-wrapper";
|
|
9
|
+
import deployCmd from "@/commands/deploy";
|
|
10
|
+
import { loginCommand } from "@/commands/login";
|
|
11
|
+
import runCmd from "@/commands/run-wrapper";
|
|
12
|
+
import secretCmd from "@/commands/secret";
|
|
13
|
+
import { upgradeCommand } from "@/commands/upgrade";
|
|
14
|
+
import { whoamiCommand } from "@/commands/whoami";
|
|
15
|
+
const parser = or(batchCmd.def, command("configure", constant("configure"), {
|
|
51
16
|
brief: message `Configure environment variables.`,
|
|
52
|
-
}), command("login", constant("login"), {
|
|
53
|
-
brief: message `
|
|
17
|
+
}), command("login", constant("login"), { brief: message `Log in to Town Shed.` }), command("upgrade", constant("upgrade"), {
|
|
18
|
+
brief: message `Upgrade dependencies by cleaning and reinstalling.`,
|
|
54
19
|
}), command("whoami", constant("whoami"), {
|
|
55
20
|
brief: message `Show current login status.`,
|
|
56
|
-
}),
|
|
57
|
-
brief: message `Upgrade dependencies by cleaning and reinstalling.`,
|
|
58
|
-
}), command("create", object({
|
|
59
|
-
command: constant("create"),
|
|
60
|
-
name: optional(option("-n", "--name", string())),
|
|
61
|
-
model: optional(option("-m", "--model", string())),
|
|
62
|
-
tools: multiple(option("-t", "--tool", string())),
|
|
63
|
-
systemPrompt: optional(option("-p", "--prompt", string())),
|
|
64
|
-
init: optional(option("--init", string())),
|
|
65
|
-
claude: optional(flag("--claude")),
|
|
66
|
-
}), {
|
|
67
|
-
brief: message `Create a new agent or project (with --init <path>). Use --claude to add Claude Code integration.`,
|
|
68
|
-
}), command("run", object({
|
|
69
|
-
command: constant("run"),
|
|
70
|
-
name: argument(string({ metavar: "NAME" })),
|
|
71
|
-
http: optional(flag("--http")),
|
|
72
|
-
gui: optional(flag("--gui")),
|
|
73
|
-
cli: optional(flag("--cli")),
|
|
74
|
-
prompt: optional(argument(string({ metavar: "PROMPT" }))),
|
|
75
|
-
port: optional(option("-p", "--port", integer())),
|
|
76
|
-
noSession: optional(flag("--no-session")),
|
|
77
|
-
}), { brief: message `Run an agent.` }), command("batch", object({
|
|
78
|
-
command: constant("batch"),
|
|
79
|
-
name: argument(string({ metavar: "NAME" })),
|
|
80
|
-
queries: multiple(argument(string({ metavar: "QUERY" }))),
|
|
81
|
-
file: optional(option("-f", "--file", string())),
|
|
82
|
-
concurrency: optional(option("-c", "--concurrency", integer())),
|
|
83
|
-
port: optional(option("-p", "--port", integer())),
|
|
84
|
-
}), {
|
|
85
|
-
brief: message `Run multiple queries in parallel against an agent.`,
|
|
86
|
-
description: message `Run multiple queries in parallel, each in its own session. Queries can be provided as arguments or loaded from a file.`,
|
|
87
|
-
}), command("secret", object({
|
|
88
|
-
command: constant("secret"),
|
|
89
|
-
subcommand: or(command("list", object({ action: constant("list") }), {
|
|
90
|
-
brief: message `List secrets.`,
|
|
91
|
-
}), command("add", object({
|
|
92
|
-
action: constant("add"),
|
|
93
|
-
name: argument(string({ metavar: "NAME" })),
|
|
94
|
-
value: optional(argument(string({ metavar: "VALUE" }))),
|
|
95
|
-
}), { brief: message `Add a secret.` }), command("update", object({
|
|
96
|
-
action: constant("update"),
|
|
97
|
-
name: optional(argument(string({ metavar: "NAME" }))),
|
|
98
|
-
value: optional(argument(string({ metavar: "VALUE" }))),
|
|
99
|
-
genenv: optional(flag("-g", "--genenv", {
|
|
100
|
-
description: message `Regenerate .env file.`,
|
|
101
|
-
})),
|
|
102
|
-
}), { brief: message `Update a secret.` }), command("remove", object({
|
|
103
|
-
action: constant("remove"),
|
|
104
|
-
name: argument(string({ metavar: "NAME" })),
|
|
105
|
-
}), { brief: message `Remove a secret.` }), command("genenv", object({ action: constant("genenv") }), {
|
|
106
|
-
brief: message `Generate .env file.`,
|
|
107
|
-
})),
|
|
108
|
-
}), { brief: message `Secrets management.` }));
|
|
21
|
+
}), createCmd.def, deployCmd.def, runCmd.def, secretCmd.def);
|
|
109
22
|
const meta = {
|
|
110
23
|
programName: "town",
|
|
111
24
|
help: "both",
|
|
@@ -115,245 +28,15 @@ const meta = {
|
|
|
115
28
|
description: message `Town CLI is a first-class command-line experience for working with Town Agents.`,
|
|
116
29
|
};
|
|
117
30
|
const main = async (parser, meta) => await match(run(parser, meta))
|
|
118
|
-
.with("login", loginCommand)
|
|
119
|
-
.with("whoami", whoamiCommand)
|
|
120
|
-
.with({ command: "deploy" }, async ({ agent }) => {
|
|
121
|
-
const projectRoot = await isInsideTownProject();
|
|
122
|
-
if (!projectRoot)
|
|
123
|
-
throw new Error("Not inside a Town project");
|
|
124
|
-
if (!(await afs.exists(join(projectRoot, "agents", agent))))
|
|
125
|
-
throw new Error(`Agent ${agent} not found`);
|
|
126
|
-
const { accessToken, shedUrl } = await getValidCredentials();
|
|
127
|
-
const authHeader = { Authorization: `Bearer ${accessToken}` };
|
|
128
|
-
const url = `${shedUrl}/api/trpc`;
|
|
129
|
-
const baseLinkOpts = { url, transformer: superjson };
|
|
130
|
-
const client = createTRPCClient({
|
|
131
|
-
links: [
|
|
132
|
-
splitLink({
|
|
133
|
-
condition: (op) => op.type === "subscription",
|
|
134
|
-
true: httpSubscriptionLink({
|
|
135
|
-
...baseLinkOpts,
|
|
136
|
-
EventSource,
|
|
137
|
-
eventSourceOptions: {
|
|
138
|
-
fetch: async (url, init) => fetch(url, {
|
|
139
|
-
...init,
|
|
140
|
-
headers: { ...init.headers, ...authHeader },
|
|
141
|
-
}),
|
|
142
|
-
},
|
|
143
|
-
}),
|
|
144
|
-
false: httpLink({ ...baseLinkOpts, headers: authHeader }),
|
|
145
|
-
}),
|
|
146
|
-
],
|
|
147
|
-
});
|
|
148
|
-
console.log("Creating archive...");
|
|
149
|
-
const root = await findRoot({ rootMarker: "package.json" });
|
|
150
|
-
const arc = archiver("tar", { gzip: true });
|
|
151
|
-
const chunks = [];
|
|
152
|
-
const done = new Promise((ok, err) => {
|
|
153
|
-
arc.on("data", (chunk) => chunks.push(chunk));
|
|
154
|
-
arc.on("end", () => ok(Buffer.concat(chunks)));
|
|
155
|
-
arc.on("error", err);
|
|
156
|
-
});
|
|
157
|
-
(await walk({ path: root, ignoreFiles: [".gitignore"] }))
|
|
158
|
-
.filter((path) => path.split("/")[0] !== ".git")
|
|
159
|
-
.forEach((path) => {
|
|
160
|
-
if (!fs.statSync(path).isFile())
|
|
161
|
-
return;
|
|
162
|
-
arc.append(fs.createReadStream(path), { name: path });
|
|
163
|
-
});
|
|
164
|
-
arc.finalize();
|
|
165
|
-
console.log("Uploading archive...");
|
|
166
|
-
const { sha256, cached } = await client.uploadArchive.mutate(await done);
|
|
167
|
-
console.log(`Archive uploaded: ${sha256} (${cached ? "cached" : "new"})`);
|
|
168
|
-
console.log("Deploying...");
|
|
169
|
-
client.deploy.subscribe({ sha256, agent, shedUrl }, {
|
|
170
|
-
onData: ({ status, error }) => console.log(status ? status : error),
|
|
171
|
-
onError: (err) => console.error(err),
|
|
172
|
-
onComplete: () => console.log("\n✓ Deployment complete!"),
|
|
173
|
-
});
|
|
174
|
-
})
|
|
175
31
|
.with("configure", configureCommand)
|
|
32
|
+
.with("login", loginCommand)
|
|
176
33
|
.with("upgrade", upgradeCommand)
|
|
177
|
-
.with(
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
// Check if we're in a Town project
|
|
185
|
-
const projectRoot = await isInsideTownProject();
|
|
186
|
-
if (projectRoot === null) {
|
|
187
|
-
console.error("Error: Not inside a Town project. Use 'town create --init <path>' to create a new project.");
|
|
188
|
-
process.exit(1);
|
|
189
|
-
}
|
|
190
|
-
// Initialize .claude directory only
|
|
191
|
-
await initForClaudeCode(projectRoot);
|
|
192
|
-
console.log("\n✓ Claude Code workspace initialized successfully!");
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
// Check if --init flag is present for project scaffolding
|
|
196
|
-
if (init !== null && init !== undefined) {
|
|
197
|
-
// Project mode - scaffold a standalone project
|
|
198
|
-
await createProjectCommand({
|
|
199
|
-
path: init,
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
else {
|
|
203
|
-
// Check if we're inside a Town project
|
|
204
|
-
const projectRoot = await isInsideTownProject();
|
|
205
|
-
if (projectRoot === null) {
|
|
206
|
-
// Not in a project - prompt user to initialize
|
|
207
|
-
const answer = await inquirer.prompt([
|
|
208
|
-
{
|
|
209
|
-
type: "confirm",
|
|
210
|
-
name: "initProject",
|
|
211
|
-
message: "Not inside a Town project. Initialize project in current directory?",
|
|
212
|
-
default: true,
|
|
213
|
-
},
|
|
214
|
-
]);
|
|
215
|
-
if (answer.initProject) {
|
|
216
|
-
// Initialize project first
|
|
217
|
-
await createProjectCommand({ path: process.cwd() });
|
|
218
|
-
// Then create agent
|
|
219
|
-
await createCommand({
|
|
220
|
-
...(name !== undefined && { name }),
|
|
221
|
-
...(model !== undefined && { model }),
|
|
222
|
-
...(tools.length > 0 && { tools }),
|
|
223
|
-
...(systemPrompt !== undefined && { systemPrompt }),
|
|
224
|
-
agentsDir: join(process.cwd(), "agents"),
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
else {
|
|
228
|
-
// User declined
|
|
229
|
-
console.log("\nPlease run 'town create' inside a project directory, or run:\n" +
|
|
230
|
-
" town create --init <path>\n" +
|
|
231
|
-
"to create a project.");
|
|
232
|
-
process.exit(1);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
// Agent mode - create agent in existing project
|
|
237
|
-
// Create command starts a long-running Ink session
|
|
238
|
-
await createCommand({
|
|
239
|
-
...(name !== undefined && { name }),
|
|
240
|
-
...(model !== undefined && { model }),
|
|
241
|
-
...(tools.length > 0 && { tools }),
|
|
242
|
-
...(systemPrompt !== undefined && { systemPrompt }),
|
|
243
|
-
agentsDir: join(projectRoot, "agents"),
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
})
|
|
248
|
-
.with({ command: "run" }, async ({ name, http, gui, cli, prompt, port, noSession }) => {
|
|
249
|
-
const options = {
|
|
250
|
-
name,
|
|
251
|
-
http: http === true,
|
|
252
|
-
gui: gui === true,
|
|
253
|
-
cli: cli === true,
|
|
254
|
-
noSession: noSession === true,
|
|
255
|
-
};
|
|
256
|
-
if (prompt !== null && prompt !== undefined) {
|
|
257
|
-
options.prompt = prompt;
|
|
258
|
-
}
|
|
259
|
-
if (port !== null && port !== undefined) {
|
|
260
|
-
options.port = port;
|
|
261
|
-
}
|
|
262
|
-
await runCommand(options);
|
|
263
|
-
})
|
|
264
|
-
.with({ command: "batch" }, async ({ name, queries, file, concurrency, port }) => {
|
|
265
|
-
const options = {
|
|
266
|
-
name,
|
|
267
|
-
};
|
|
268
|
-
if (queries.length > 0) {
|
|
269
|
-
options.queries = [...queries]; // Convert readonly array to mutable
|
|
270
|
-
}
|
|
271
|
-
if (file !== null && file !== undefined) {
|
|
272
|
-
options.file = file;
|
|
273
|
-
}
|
|
274
|
-
if (concurrency !== null && concurrency !== undefined) {
|
|
275
|
-
options.concurrency = concurrency;
|
|
276
|
-
}
|
|
277
|
-
if (port !== null && port !== undefined) {
|
|
278
|
-
options.port = port;
|
|
279
|
-
}
|
|
280
|
-
await batchCommand(options);
|
|
281
|
-
})
|
|
282
|
-
.with({ command: "secret" }, async ({ subcommand }) => {
|
|
283
|
-
await match(subcommand)
|
|
284
|
-
.with({ action: "list" }, async () => {
|
|
285
|
-
const truncate = (str, maxLength = 50) => {
|
|
286
|
-
if (str.length <= maxLength)
|
|
287
|
-
return str;
|
|
288
|
-
return `${str.slice(0, maxLength - 3)}...`;
|
|
289
|
-
};
|
|
290
|
-
console.table((await listSecrets()).map((secret) => ({
|
|
291
|
-
Key: secret.key,
|
|
292
|
-
Valid: secret.valid ? "✓" : "✗",
|
|
293
|
-
Error: truncate(secret.error ?? ""),
|
|
294
|
-
})));
|
|
295
|
-
})
|
|
296
|
-
.with({ action: "add" }, async ({ name, value }) => {
|
|
297
|
-
// If value is not provided, prompt securely
|
|
298
|
-
const secretValue = value ?? (await promptSecret(name));
|
|
299
|
-
if (!secretValue) {
|
|
300
|
-
console.error("Error: Secret value cannot be empty");
|
|
301
|
-
process.exit(1);
|
|
302
|
-
}
|
|
303
|
-
await createSecret(name, secretValue);
|
|
304
|
-
await updateEnvSchema();
|
|
305
|
-
console.log(`Secret '${name}' added successfully (& @packages/env schema updated).`);
|
|
306
|
-
})
|
|
307
|
-
.with({ action: "update" }, async ({ name, value, genenv: regen }) => {
|
|
308
|
-
let secretName = name;
|
|
309
|
-
// If name is not provided, show a list prompt to select from existing secrets
|
|
310
|
-
if (!secretName) {
|
|
311
|
-
const secrets = await listSecrets();
|
|
312
|
-
if (secrets.length === 0) {
|
|
313
|
-
console.error("No secrets found to update.");
|
|
314
|
-
process.exit(1);
|
|
315
|
-
}
|
|
316
|
-
const answer = await inquirer.prompt([
|
|
317
|
-
{
|
|
318
|
-
type: "list",
|
|
319
|
-
name: "selectedSecret",
|
|
320
|
-
message: "Select a secret to update:",
|
|
321
|
-
choices: secrets.map((s) => ({
|
|
322
|
-
name: `${s.key} ${s.valid ? "✓" : "✗"}`,
|
|
323
|
-
value: s.key,
|
|
324
|
-
})),
|
|
325
|
-
},
|
|
326
|
-
]);
|
|
327
|
-
secretName = answer.selectedSecret;
|
|
328
|
-
}
|
|
329
|
-
// If value is not provided, prompt securely
|
|
330
|
-
if (!secretName) {
|
|
331
|
-
console.error("Error: Secret name is required");
|
|
332
|
-
process.exit(1);
|
|
333
|
-
}
|
|
334
|
-
const secretValue = value ?? (await promptSecret(secretName));
|
|
335
|
-
if (!secretValue) {
|
|
336
|
-
console.error("Error: Secret value cannot be empty");
|
|
337
|
-
process.exit(1);
|
|
338
|
-
}
|
|
339
|
-
await updateSecret(secretName, secretValue);
|
|
340
|
-
console.log(`Secret '${secretName}' updated successfully.`);
|
|
341
|
-
if (regen) {
|
|
342
|
-
await genenv();
|
|
343
|
-
console.log(".env file generated successfully.");
|
|
344
|
-
}
|
|
345
|
-
})
|
|
346
|
-
.with({ action: "remove" }, async ({ name }) => {
|
|
347
|
-
await deleteSecret(name);
|
|
348
|
-
await updateEnvSchema();
|
|
349
|
-
console.log(`Secret '${name}' removed successfully (& @packages/env schema updated).`);
|
|
350
|
-
})
|
|
351
|
-
.with({ action: "genenv" }, async () => {
|
|
352
|
-
await genenv();
|
|
353
|
-
console.log(".env file generated successfully.");
|
|
354
|
-
})
|
|
355
|
-
.exhaustive();
|
|
356
|
-
})
|
|
34
|
+
.with("whoami", whoamiCommand)
|
|
35
|
+
.with({ command: "batch" }, batchCmd.impl)
|
|
36
|
+
.with({ command: "create" }, createCmd.impl)
|
|
37
|
+
.with({ command: "deploy" }, deployCmd.impl)
|
|
38
|
+
.with({ command: "run" }, runCmd.impl)
|
|
39
|
+
.with({ command: "secret" }, secretCmd.impl)
|
|
357
40
|
.exhaustive();
|
|
358
41
|
main(parser, meta).catch((error) => {
|
|
359
42
|
console.error("Error:", error);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { InferValue } from "@optique/core";
|
|
2
|
+
export declare const createCommand: <T extends import("@optique/core").Parser<unknown, ["matched", string] | ["parsing", unknown] | undefined>>({ def, impl, }: {
|
|
3
|
+
def: T;
|
|
4
|
+
impl: (def: InferValue<T>) => unknown;
|
|
5
|
+
}) => {
|
|
6
|
+
def: T;
|
|
7
|
+
impl: (def: InferValue<T>) => unknown;
|
|
8
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const createCommand = ({ def, impl, }) => ({ def, impl });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@townco/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.84",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"town": "./dist/index.js"
|
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
],
|
|
12
12
|
"repository": "github:townco/town",
|
|
13
13
|
"scripts": {
|
|
14
|
-
"check": "
|
|
15
|
-
"build": "
|
|
14
|
+
"check": "tsgo --noEmit",
|
|
15
|
+
"build": "tsgo"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@townco/tsconfig": "0.1.
|
|
18
|
+
"@townco/tsconfig": "0.1.76",
|
|
19
19
|
"@types/archiver": "^7.0.0",
|
|
20
20
|
"@types/bun": "^1.3.1",
|
|
21
21
|
"@types/ignore-walk": "^4.0.3",
|
|
@@ -25,26 +25,22 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@optique/core": "^0.6.2",
|
|
27
27
|
"@optique/run": "^0.6.2",
|
|
28
|
-
"@townco/agent": "0.1.
|
|
29
|
-
"@townco/core": "0.0.
|
|
30
|
-
"@townco/debugger": "0.1.
|
|
31
|
-
"@townco/env": "0.1.
|
|
32
|
-
"@townco/secret": "0.1.
|
|
33
|
-
"@townco/ui": "0.1.
|
|
28
|
+
"@townco/agent": "0.1.84",
|
|
29
|
+
"@townco/core": "0.0.57",
|
|
30
|
+
"@townco/debugger": "0.1.34",
|
|
31
|
+
"@townco/env": "0.1.29",
|
|
32
|
+
"@townco/secret": "0.1.79",
|
|
33
|
+
"@townco/ui": "0.1.79",
|
|
34
34
|
"@trpc/client": "^11.7.2",
|
|
35
|
-
"@types/inquirer": "^9.0.9",
|
|
36
|
-
"@types/ws": "^8.5.13",
|
|
37
35
|
"archiver": "^7.0.1",
|
|
38
36
|
"eventsource": "^4.1.0",
|
|
39
|
-
"ignore": "^7.0.5",
|
|
40
37
|
"ignore-walk": "^8.0.0",
|
|
41
38
|
"ink": "^6.4.0",
|
|
42
39
|
"ink-text-input": "^6.0.0",
|
|
43
40
|
"inquirer": "^12.10.0",
|
|
44
41
|
"open": "^10.2.0",
|
|
45
42
|
"superjson": "^2.2.5",
|
|
46
|
-
"ts-pattern": "^5.9.0"
|
|
47
|
-
"ws": "^8.18.0"
|
|
43
|
+
"ts-pattern": "^5.9.0"
|
|
48
44
|
},
|
|
49
45
|
"peerDependencies": {
|
|
50
46
|
"react": ">=19.0.0"
|