@trikhub/cli 0.17.0 → 0.17.1-dev.1

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.
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @deprecated Use @trikhub/linter instead.
3
+ *
4
+ * v1 validator removed in P1. All validation now through @trikhub/linter.
5
+ */
6
+ export interface ValidationResult {
7
+ valid: boolean;
8
+ errors: string[];
9
+ warnings: string[];
10
+ }
11
+ export declare function validateTrik(_trikPath: string): ValidationResult;
12
+ export declare function formatValidationResult(result: ValidationResult): string;
13
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/lib/validator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAEhE;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAEvE"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @deprecated Use @trikhub/linter instead.
3
+ *
4
+ * v1 validator removed in P1. All validation now through @trikhub/linter.
5
+ */
6
+ export function validateTrik(_trikPath) {
7
+ return { valid: true, errors: [], warnings: [] };
8
+ }
9
+ export function formatValidationResult(result) {
10
+ return result.valid ? 'Validation passed' : 'Validation failed';
11
+ }
12
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/lib/validator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAwB;IAC7D,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,mBAAmB,CAAC;AAClE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-python.d.ts","sourceRoot":"","sources":["../../src/templates/agent-python.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AA0L/D;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAW5F"}
1
+ {"version":3,"file":"agent-python.d.ts","sourceRoot":"","sources":["../../src/templates/agent-python.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AA+X/D;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgB5F"}
@@ -47,13 +47,17 @@ dependencies = [
47
47
  "langchain-core>=0.3.0",
48
48
  "langgraph>=0.2.0",
49
49
  "trikhub>=0.6.0",
50
- "python-dotenv>=1.0.0",
50
+ "python-dotenv>=1.0.0",${config.channels === 'cli+telegram' ? `\n "python-telegram-bot>=21.0",` : ''}
51
51
  ]
52
52
  `;
53
53
  }
54
54
  function generateEnvExample(config) {
55
55
  const provider = PROVIDERS[config.provider];
56
- return `${provider.envVar}=your-api-key-here\n`;
56
+ let env = `${provider.envVar}=your-api-key-here\n`;
57
+ if (config.channels === 'cli+telegram') {
58
+ env += `TELEGRAM_BOT_TOKEN=your-token-from-botfather\n`;
59
+ }
60
+ return env;
57
61
  }
58
62
  function generateGitignore() {
59
63
  return `__pycache__/
@@ -77,32 +81,35 @@ from __future__ import annotations
77
81
  from ${provider.importPath} import ${provider.className}
78
82
  from langgraph.prebuilt import create_react_agent
79
83
 
80
- from trikhub.gateway import TrikGateway
81
- from trikhub.langchain import enhance, get_handoff_tools_for_agent, get_exposed_tools_for_agent
84
+ from trikhub.langchain import enhance, EnhanceOptions
85
+
86
+ SYSTEM_PROMPT = """You are a helpful agent spawned by Trikhub. A user has installed you and you are ready to install Triks to help them with various tasks. You can call any tools provided by the installed Triks to assist the user.
87
+ Feel free to propose a few starting Triks that the user should use to test out your capabilitites:
88
+ - @molefas/trikster: The first Trik anyone should have. This allows you to install other Triks, which will expand your capabilities with new tools and handoffs.
89
+ - @molefas/site-builder: A Demo Trik for building websites. It's meant to showcase how Triks can generate files and execute commands in a safe environment (docker container). With this Trik, you can build a static website by describing it to the agent, which will generate the necessary HTML/CSS/JS files and even run a local server for you to preview it.
90
+ - @molefas/trik-hash: A Demo Trik to showcase basic Tool-like triks, with no conversational skill. It provides a simple hashing tool that can hash any input with various algorithms (md5, sha256, etc). It's a great starting point to understand how to call tools from your agent.
91
+ - @molefas/ghost-writer: A Demo Trik to showcase persistent storage capabilitites and how a full-fledged Trik can be. It also exposes a web interface for users to interact with their data.
92
+
93
+ Other useful tips:
94
+ - Users can do trik list to see installed triks and trik search <query> to find new ones.
95
+ - Users can refer to the Trikhub documentation at https://docs.trikhub.com for more details on how to use and create triks.
96
+ - If you've chosen the Telegram installation, check the readme for instructions on how to interact with your agent via Telegram.
82
97
 
83
- SYSTEM_PROMPT = """You are a helpful assistant.
84
98
  When a trik can handle the user's request, use the appropriate tool."""
85
99
 
86
100
 
87
101
  async def initialize_agent():
88
102
  model = ${provider.className}(model="${provider.defaultModel}")
89
103
 
90
- gateway = TrikGateway()
91
- await gateway.initialize()
92
- await gateway.load_triks_from_config()
93
-
94
- handoff_tools = get_handoff_tools_for_agent(gateway)
95
- exposed_tools = get_exposed_tools_for_agent(gateway)
96
-
97
- agent = create_react_agent(
98
- model=model,
99
- tools=[*handoff_tools, *exposed_tools],
100
- prompt=SYSTEM_PROMPT,
101
- )
102
-
103
- app = await enhance(agent, gateway_instance=gateway)
104
+ app = await enhance(None, EnhanceOptions(
105
+ create_agent=lambda trik_tools: create_react_agent(
106
+ model=model,
107
+ tools=list(trik_tools),
108
+ prompt=SYSTEM_PROMPT,
109
+ ),
110
+ ))
104
111
 
105
- return app, handoff_tools, exposed_tools
112
+ return app
106
113
  `;
107
114
  }
108
115
  function generateCliPy() {
@@ -123,13 +130,13 @@ from agent import initialize_agent
123
130
  async def main() -> None:
124
131
  print("Loading agent...\\n")
125
132
 
126
- app, handoff_tools, exposed_tools = await initialize_agent()
133
+ app = await initialize_agent()
127
134
 
128
- if handoff_tools:
129
- print(f"Handoff triks: {', '.join(t.name for t in handoff_tools)}")
130
- if exposed_tools:
131
- print(f"Tool-mode triks: {', '.join(t.name for t in exposed_tools)}")
132
- print('Type "/back" to return from a trik handoff, "exit" to quit.\\n')
135
+ loaded_triks = app.get_loaded_triks()
136
+ if loaded_triks:
137
+ print(f"Loaded triks: {', '.join(loaded_triks)}")
138
+ print('Type "/back" to return from a trik handoff, "exit" to quit.')
139
+ print('Tip: Ask the Agent what to do next\\n')
133
140
 
134
141
  session_id = f"cli-{id(app)}"
135
142
 
@@ -164,6 +171,188 @@ if __name__ == "__main__":
164
171
  asyncio.run(main())
165
172
  `;
166
173
  }
174
+ function generateTelegramPy() {
175
+ return `#!/usr/bin/env python3
176
+ """Telegram bot for the TrikHub-powered agent."""
177
+
178
+ from __future__ import annotations
179
+
180
+ import asyncio
181
+ import logging
182
+ import os
183
+ import time
184
+
185
+ from dotenv import load_dotenv
186
+
187
+ load_dotenv()
188
+
189
+ from telegram import Update
190
+ from telegram.ext import Application, MessageHandler, filters, ContextTypes
191
+
192
+ from agent import initialize_agent
193
+
194
+ logging.basicConfig(level=logging.INFO)
195
+ logger = logging.getLogger(__name__)
196
+
197
+
198
+ async def main() -> None:
199
+ print("Loading agent...\\n")
200
+
201
+ app = await initialize_agent()
202
+
203
+ loaded_triks = app.get_loaded_triks()
204
+ if loaded_triks:
205
+ print(f"Loaded triks: {', '.join(loaded_triks)}")
206
+
207
+ token = os.environ.get("TELEGRAM_BOT_TOKEN")
208
+ if not token:
209
+ print("TELEGRAM_BOT_TOKEN is not set in .env")
210
+ raise SystemExit(1)
211
+
212
+ session_id = f"telegram-{int(time.time())}"
213
+
214
+ async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
215
+ if not update.message or not update.message.text:
216
+ return
217
+ try:
218
+ result = await app.process_message(update.message.text, session_id)
219
+ await update.message.reply_text(result.message)
220
+ except Exception as e:
221
+ logger.error("Error processing message: %s", e)
222
+ await update.message.reply_text("Something went wrong. Please try again.")
223
+
224
+ application = Application.builder().token(token).build()
225
+ application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
226
+
227
+ print("\\nTelegram bot started! Send a message to your bot.\\n")
228
+ await application.run_polling()
229
+
230
+
231
+ if __name__ == "__main__":
232
+ asyncio.run(main())
233
+ `;
234
+ }
235
+ function generateReadme(config) {
236
+ const provider = PROVIDERS[config.provider];
237
+ const hasTelegram = config.channels === 'cli+telegram';
238
+ let readme = `# ${config.name}
239
+
240
+ An AI agent powered by [TrikHub](https://trikhub.com). This agent uses **${provider.className}** and can be extended with triks — composable capabilities that plug into your agent.
241
+
242
+ ## What can this agent do?
243
+
244
+ Out of the box, your agent is a general-purpose assistant. Its real power comes from **triks** — install them to give your agent new capabilities:
245
+
246
+ \`\`\`bash
247
+ # Browse and search available triks
248
+ trik search <query>
249
+
250
+ # Install a trik
251
+ trik install @scope/trik-name
252
+ \`\`\`
253
+
254
+ Triks come in two flavors:
255
+ - **Handoff triks** — take over the conversation for a specialized task (e.g. a coding assistant, a travel planner). Use \`/back\` to return.
256
+ - **Tool triks** — appear as native tools the agent can call (e.g. web search, calculator).
257
+
258
+ ## Setup
259
+
260
+ \`\`\`bash
261
+ python -m venv .venv
262
+ source .venv/bin/activate # Windows: .venv\\Scripts\\activate
263
+ pip install -e .
264
+ cp .env.example .env
265
+ \`\`\`
266
+
267
+ Add your **${provider.envVar}** to \`.env\`.
268
+ `;
269
+ if (hasTelegram) {
270
+ readme += `
271
+ ### Telegram Bot Token
272
+
273
+ To run the Telegram bot, you need a bot token:
274
+
275
+ 1. Open Telegram and message [@BotFather](https://t.me/BotFather)
276
+ 2. Send \`/newbot\`
277
+ 3. Choose a display name (e.g. "${config.name}")
278
+ 4. Choose a username (must end in \`bot\`, e.g. \`${config.name.replace(/-/g, '_')}_bot\`)
279
+ 5. Copy the token into \`.env\` as \`TELEGRAM_BOT_TOKEN\`
280
+ `;
281
+ }
282
+ readme += `
283
+ ## Running
284
+
285
+ ### CLI mode
286
+
287
+ \`\`\`bash
288
+ python cli.py
289
+ \`\`\`
290
+
291
+ Chat with your agent in the terminal. Type \`/back\` to return from a trik handoff, \`exit\` to quit.
292
+ `;
293
+ if (hasTelegram) {
294
+ readme += `
295
+ ### Telegram mode
296
+
297
+ \`\`\`bash
298
+ python telegram_bot.py
299
+ \`\`\`
300
+
301
+ Your agent runs as a Telegram bot. Open Telegram, find your bot by username, and start chatting.
302
+
303
+ ## Keeping your bot running
304
+
305
+ The Telegram bot needs to stay running to receive messages. Here are a few options:
306
+
307
+ ### pm2 (Recommended)
308
+
309
+ \`\`\`bash
310
+ npm install -g pm2
311
+ pm2 start python --name "${config.name}" -- telegram_bot.py
312
+ pm2 save
313
+ pm2 startup # auto-start on boot
314
+ \`\`\`
315
+
316
+ ### Docker
317
+
318
+ \`\`\`dockerfile
319
+ FROM python:3.12-slim
320
+ WORKDIR /app
321
+ COPY pyproject.toml .
322
+ COPY *.py .
323
+ RUN pip install .
324
+ CMD ["python", "telegram_bot.py"]
325
+ \`\`\`
326
+
327
+ ### systemd (Linux VPS)
328
+
329
+ \`\`\`ini
330
+ [Unit]
331
+ Description=${config.name} Telegram bot
332
+ After=network.target
333
+
334
+ [Service]
335
+ ExecStart=/home/user/${config.name}/.venv/bin/python /home/user/${config.name}/telegram_bot.py
336
+ WorkingDirectory=/home/user/${config.name}
337
+ Restart=always
338
+ EnvironmentFile=/home/user/${config.name}/.env
339
+
340
+ [Install]
341
+ WantedBy=multi-user.target
342
+ \`\`\`
343
+ `;
344
+ }
345
+ readme += `
346
+ ## Installing triks
347
+
348
+ \`\`\`bash
349
+ trik install @scope/trik-name
350
+ \`\`\`
351
+
352
+ Installed triks are saved to \`.trikhub/config.json\` and loaded automatically when your agent starts.
353
+ `;
354
+ return readme;
355
+ }
167
356
  // ============================================================================
168
357
  // Public API
169
358
  // ============================================================================
@@ -178,8 +367,12 @@ export function generateAgentPythonProject(config) {
178
367
  files['.env.example'] = generateEnvExample(config);
179
368
  files['.gitignore'] = generateGitignore();
180
369
  files['.trikhub/config.json'] = generateTrikhubConfig();
370
+ files['README.md'] = generateReadme(config);
181
371
  files['agent.py'] = generateAgentPy(config);
182
372
  files['cli.py'] = generateCliPy();
373
+ if (config.channels === 'cli+telegram') {
374
+ files['telegram_bot.py'] = generateTelegramPy();
375
+ }
183
376
  return files;
184
377
  }
185
378
  //# sourceMappingURL=agent-python.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-python.js","sourceRoot":"","sources":["../../src/templates/agent-python.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAgBH,MAAM,SAAS,GAAiC;IAC9C,MAAM,EAAE;QACN,UAAU,EAAE,kBAAkB;QAC9B,SAAS,EAAE,YAAY;QACvB,UAAU,EAAE,kBAAkB;QAC9B,YAAY,EAAE,aAAa;QAC3B,MAAM,EAAE,gBAAgB;KACzB;IACD,SAAS,EAAE;QACT,UAAU,EAAE,qBAAqB;QACjC,SAAS,EAAE,eAAe;QAC1B,UAAU,EAAE,qBAAqB;QACjC,YAAY,EAAE,0BAA0B;QACxC,MAAM,EAAE,mBAAmB;KAC5B;IACD,MAAM,EAAE;QACN,UAAU,EAAE,wBAAwB;QACpC,SAAS,EAAE,wBAAwB;QACnC,UAAU,EAAE,wBAAwB;QACpC,YAAY,EAAE,kBAAkB;QAChC,MAAM,EAAE,gBAAgB;KACzB;CACF,CAAC;AAEF,+EAA+E;AAC/E,kBAAkB;AAClB,+EAA+E;AAE/E,SAAS,qBAAqB,CAAC,MAAyB;IACtD,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5C,OAAO;;;;;UAKC,MAAM,CAAC,IAAI;;;;;;OAMd,QAAQ,CAAC,UAAU;;;;;;CAMzB,CAAC;AACF,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAyB;IACnD,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5C,OAAO,GAAG,QAAQ,CAAC,MAAM,sBAAsB,CAAC;AAClD,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO;;;;;;;CAOR,CAAC;AACF,CAAC;AAED,SAAS,qBAAqB;IAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,eAAe,CAAC,MAAyB;IAChD,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5C,OAAO;;;;OAIF,QAAQ,CAAC,UAAU,WAAW,QAAQ,CAAC,SAAS;;;;;;;;;;;cAWzC,QAAQ,CAAC,SAAS,WAAW,QAAQ,CAAC,YAAY;;;;;;;;;;;;;;;;;;CAkB/D,CAAC;AACF,CAAC;AAED,SAAS,aAAa;IACpB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwDR,CAAC;AACF,CAAC;AAED,+EAA+E;AAC/E,aAAa;AACb,+EAA+E;AAE/E;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CAAC,MAAyB;IAClE,MAAM,KAAK,GAA2B,EAAE,CAAC;IAEzC,KAAK,CAAC,gBAAgB,CAAC,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACxD,KAAK,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACnD,KAAK,CAAC,YAAY,CAAC,GAAG,iBAAiB,EAAE,CAAC;IAC1C,KAAK,CAAC,sBAAsB,CAAC,GAAG,qBAAqB,EAAE,CAAC;IACxD,KAAK,CAAC,UAAU,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,CAAC,QAAQ,CAAC,GAAG,aAAa,EAAE,CAAC;IAElC,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"agent-python.js","sourceRoot":"","sources":["../../src/templates/agent-python.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@
8
8
  export interface CreateAgentConfig {
9
9
  name: string;
10
10
  provider: 'openai' | 'anthropic' | 'google';
11
+ channels?: 'cli' | 'cli+telegram';
11
12
  }
12
13
  /**
13
14
  * Generate a complete TypeScript agent project ready to consume triks.
@@ -1 +1 @@
1
- {"version":3,"file":"agent-typescript.d.ts","sourceRoot":"","sources":["../../src/templates/agent-typescript.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;CAC7C;AA+MD;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYhG"}
1
+ {"version":3,"file":"agent-typescript.d.ts","sourceRoot":"","sources":["../../src/templates/agent-typescript.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC5C,QAAQ,CAAC,EAAE,KAAK,GAAG,cAAc,CAAC;CACnC;AA8YD;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiBhG"}
@@ -33,22 +33,31 @@ const PROVIDERS = {
33
33
  // ============================================================================
34
34
  function generatePackageJson(config) {
35
35
  const provider = PROVIDERS[config.provider];
36
+ const hasTelegram = config.channels === 'cli+telegram';
37
+ const scripts = {
38
+ dev: 'node --import tsx src/cli.ts',
39
+ build: 'tsc',
40
+ };
41
+ if (hasTelegram) {
42
+ scripts.telegram = 'node --import tsx src/telegram.ts';
43
+ }
44
+ const dependencies = {
45
+ [provider.npmPackage]: '^1.0.0',
46
+ '@langchain/core': '^1.0.0',
47
+ '@langchain/langgraph': '^1.0.0',
48
+ '@trikhub/gateway': 'latest',
49
+ dotenv: '^16.4.0',
50
+ };
51
+ if (hasTelegram) {
52
+ dependencies.grammy = '^1.0.0';
53
+ }
36
54
  const pkg = {
37
55
  name: config.name,
38
56
  version: '0.1.0',
39
57
  description: 'AI agent powered by TrikHub',
40
58
  type: 'module',
41
- scripts: {
42
- dev: 'node --import tsx src/cli.ts',
43
- build: 'tsc',
44
- },
45
- dependencies: {
46
- [provider.npmPackage]: '^1.0.0',
47
- '@langchain/core': '^1.0.0',
48
- '@langchain/langgraph': '^1.0.0',
49
- '@trikhub/gateway': 'latest',
50
- dotenv: '^16.4.0',
51
- },
59
+ scripts,
60
+ dependencies,
52
61
  devDependencies: {
53
62
  tsx: '^4.19.0',
54
63
  typescript: '^5.7.0',
@@ -76,7 +85,11 @@ function generateTsConfig() {
76
85
  }
77
86
  function generateEnvExample(config) {
78
87
  const provider = PROVIDERS[config.provider];
79
- return `${provider.envVar}=your-api-key-here\n`;
88
+ let env = `${provider.envVar}=your-api-key-here\n`;
89
+ if (config.channels === 'cli+telegram') {
90
+ env += `TELEGRAM_BOT_TOKEN=your-token-from-botfather\n`;
91
+ }
92
+ return env;
80
93
  }
81
94
  function generateGitignore() {
82
95
  return `node_modules/
@@ -94,31 +107,35 @@ function generateAgentTs(config) {
94
107
  const modelParam = config.provider === 'anthropic' ? 'modelName' : 'model';
95
108
  return `import { ${provider.className} } from '${provider.importPath}';
96
109
  import { createReactAgent } from '@langchain/langgraph/prebuilt';
97
- import { TrikGateway } from '@trikhub/gateway';
98
- import { enhance, getHandoffToolsForAgent, getExposedToolsForAgent } from '@trikhub/gateway/langchain';
110
+ import { enhance } from '@trikhub/gateway/langchain';
111
+
112
+ const SYSTEM_PROMPT = \`You are a helpful agent spawned by Trikhub. A user has installed you and you are ready to install Triks to help them with various tasks. You can call any tools provided by the installed Triks to assist the user.
113
+ Feel free to propose a few starting Triks that the user should use to test out your capabilitites:
114
+ - @molefas/trikster: The first Trik anyone should have. This allows you to install other Triks, which will expand your capabilities with new tools and handoffs.
115
+ - @molefas/site-builder: A Demo Trik for building websites. It's meant to showcase how Triks can generate files and execute commands in a safe environment (docker container). With this Trik, you can build a static website by describing it to the agent, which will generate the necessary HTML/CSS/JS files and even run a local server for you to preview it.
116
+ - @molefas/trik-hash: A Demo Trik to showcase basic Tool-like triks, with no conversational skill. It provides a simple hashing tool that can hash any input with various algorithms (md5, sha256, etc). It's a great starting point to understand how to call tools from your agent.
117
+ - @molefas/ghost-writer: A Demo Trik to showcase persistent storage capabilitites and how a full-fledged Trik can be. It also exposes a web interface for users to interact with their data.
118
+
119
+ Other useful tips:
120
+ - Users can do trik list to see installed triks and trik search <query> to find new ones.
121
+ - Users can refer to the Trikhub documentation at https://docs.trikhub.com for more details on how to use and create triks.
122
+ - If you've chosen the Telegram installation, check the readme for instructions on how to interact with your agent via Telegram.
99
123
 
100
- const SYSTEM_PROMPT = \`You are a helpful assistant.
101
124
  When a trik can handle the user's request, use the appropriate tool.\`;
102
125
 
103
126
  export async function initializeAgent() {
104
127
  const model = new ${provider.className}({ ${modelParam}: '${provider.defaultModel}' });
105
128
 
106
- const gateway = new TrikGateway();
107
- await gateway.initialize();
108
- await gateway.loadTriksFromConfig();
109
-
110
- const handoffTools = getHandoffToolsForAgent(gateway);
111
- const exposedTools = getExposedToolsForAgent(gateway);
112
-
113
- const agent = createReactAgent({
114
- llm: model,
115
- tools: [...handoffTools, ...exposedTools] as any,
116
- messageModifier: SYSTEM_PROMPT,
129
+ const app = await enhance(null, {
130
+ createAgent: (trikTools) =>
131
+ createReactAgent({
132
+ llm: model,
133
+ tools: [...trikTools] as any,
134
+ messageModifier: SYSTEM_PROMPT,
135
+ }),
117
136
  });
118
137
 
119
- const app = await enhance(agent as any, { gatewayInstance: gateway });
120
-
121
- return { app, handoffTools, exposedTools };
138
+ return app;
122
139
  }
123
140
  `;
124
141
  }
@@ -141,15 +158,14 @@ function prompt(question: string): Promise<string> {
141
158
  async function main() {
142
159
  console.log('Loading agent...\\n');
143
160
 
144
- const { app, handoffTools, exposedTools } = await initializeAgent();
161
+ const app = await initializeAgent();
145
162
 
146
- if (handoffTools.length > 0) {
147
- console.log(\`Handoff triks: \${handoffTools.map((t) => t.name).join(', ')}\`);
148
- }
149
- if (exposedTools.length > 0) {
150
- console.log(\`Tool-mode triks: \${exposedTools.map((t) => t.name).join(', ')}\`);
163
+ const loadedTriks = app.getLoadedTriks();
164
+ if (loadedTriks.length > 0) {
165
+ console.log(\`Loaded triks: \${loadedTriks.join(', ')}\`);
151
166
  }
152
- console.log('Type "/back" to return from a trik handoff, "exit" to quit.\\n');
167
+ console.log('Type "/back" to return from a trik handoff, "exit" to quit.');
168
+ console.log('Tip: Ask the Agent what to do next\\n');
153
169
 
154
170
  const sessionId = \`cli-\${Date.now()}\`;
155
171
 
@@ -187,6 +203,170 @@ main().catch((error) => {
187
203
  });
188
204
  `;
189
205
  }
206
+ function generateTelegramTs() {
207
+ return `import 'dotenv/config';
208
+ import { Bot } from 'grammy';
209
+ import { initializeAgent } from './agent.js';
210
+
211
+ async function main() {
212
+ console.log('Loading agent...\\n');
213
+
214
+ const app = await initializeAgent();
215
+
216
+ const loadedTriks = app.getLoadedTriks();
217
+ if (loadedTriks.length > 0) {
218
+ console.log(\`Loaded triks: \${loadedTriks.join(', ')}\`);
219
+ }
220
+
221
+ const token = process.env.TELEGRAM_BOT_TOKEN;
222
+ if (!token) {
223
+ console.error('TELEGRAM_BOT_TOKEN is not set in .env');
224
+ process.exit(1);
225
+ }
226
+
227
+ const bot = new Bot(token);
228
+ const sessionId = \`telegram-\${Date.now()}\`;
229
+
230
+ bot.on('message:text', async (ctx) => {
231
+ try {
232
+ const result = await app.processMessage(ctx.message.text, sessionId);
233
+ await ctx.reply(result.message);
234
+ } catch (error) {
235
+ console.error('Error processing message:', error);
236
+ await ctx.reply('Something went wrong. Please try again.');
237
+ }
238
+ });
239
+
240
+ bot.catch((err) => {
241
+ console.error('Bot error:', err);
242
+ });
243
+
244
+ console.log('\\nTelegram bot started! Send a message to your bot.\\n');
245
+ bot.start();
246
+ }
247
+
248
+ main().catch(console.error);
249
+ `;
250
+ }
251
+ function generateReadme(config) {
252
+ const provider = PROVIDERS[config.provider];
253
+ const hasTelegram = config.channels === 'cli+telegram';
254
+ let readme = `# ${config.name}
255
+
256
+ An AI agent powered by [TrikHub](https://trikhub.com). This agent uses **${provider.className}** and can be extended with triks — composable capabilities that plug into your agent.
257
+
258
+ ## What can this agent do?
259
+
260
+ Out of the box, your agent is a general-purpose assistant. Its real power comes from **triks** — install them to give your agent new capabilities:
261
+
262
+ \`\`\`bash
263
+ # Browse and search available triks
264
+ trik search <query>
265
+
266
+ # Install a trik
267
+ trik install @scope/trik-name
268
+ \`\`\`
269
+
270
+ Triks come in two flavors:
271
+ - **Handoff triks** — take over the conversation for a specialized task (e.g. a coding assistant, a travel planner). Use \`/back\` to return.
272
+ - **Tool triks** — appear as native tools the agent can call (e.g. web search, calculator).
273
+
274
+ ## Setup
275
+
276
+ \`\`\`bash
277
+ cp .env.example .env
278
+ \`\`\`
279
+
280
+ Add your **${provider.envVar}** to \`.env\`.
281
+ `;
282
+ if (hasTelegram) {
283
+ readme += `
284
+ ### Telegram Bot Token
285
+
286
+ To run the Telegram bot, you need a bot token:
287
+
288
+ 1. Open Telegram and message [@BotFather](https://t.me/BotFather)
289
+ 2. Send \`/newbot\`
290
+ 3. Choose a display name (e.g. "${config.name}")
291
+ 4. Choose a username (must end in \`bot\`, e.g. \`${config.name.replace(/-/g, '_')}_bot\`)
292
+ 5. Copy the token into \`.env\` as \`TELEGRAM_BOT_TOKEN\`
293
+ `;
294
+ }
295
+ readme += `
296
+ ## Running
297
+
298
+ ### CLI mode
299
+
300
+ \`\`\`bash
301
+ npm run dev
302
+ \`\`\`
303
+
304
+ Chat with your agent in the terminal. Type \`/back\` to return from a trik handoff, \`exit\` to quit.
305
+ `;
306
+ if (hasTelegram) {
307
+ readme += `
308
+ ### Telegram mode
309
+
310
+ \`\`\`bash
311
+ npm run telegram
312
+ \`\`\`
313
+
314
+ Your agent runs as a Telegram bot. Open Telegram, find your bot by username, and start chatting.
315
+
316
+ ## Keeping your bot running
317
+
318
+ The Telegram bot needs to stay running to receive messages. Here are a few options:
319
+
320
+ ### pm2 (Recommended)
321
+
322
+ \`\`\`bash
323
+ npm install -g pm2
324
+ pm2 start npm --name "${config.name}" -- run telegram
325
+ pm2 save
326
+ pm2 startup # auto-start on boot
327
+ \`\`\`
328
+
329
+ ### Docker
330
+
331
+ \`\`\`dockerfile
332
+ FROM node:22-slim
333
+ WORKDIR /app
334
+ COPY package.json package-lock.json ./
335
+ RUN npm install --production
336
+ COPY . .
337
+ RUN npm run build
338
+ CMD ["node", "dist/telegram.js"]
339
+ \`\`\`
340
+
341
+ ### systemd (Linux VPS)
342
+
343
+ \`\`\`ini
344
+ [Unit]
345
+ Description=${config.name} Telegram bot
346
+ After=network.target
347
+
348
+ [Service]
349
+ ExecStart=/usr/bin/node /home/user/${config.name}/dist/telegram.js
350
+ WorkingDirectory=/home/user/${config.name}
351
+ Restart=always
352
+ EnvironmentFile=/home/user/${config.name}/.env
353
+
354
+ [Install]
355
+ WantedBy=multi-user.target
356
+ \`\`\`
357
+ `;
358
+ }
359
+ readme += `
360
+ ## Installing triks
361
+
362
+ \`\`\`bash
363
+ trik install @scope/trik-name
364
+ \`\`\`
365
+
366
+ Installed triks are saved to \`.trikhub/config.json\` and loaded automatically when your agent starts.
367
+ `;
368
+ return readme;
369
+ }
190
370
  // ============================================================================
191
371
  // Public API
192
372
  // ============================================================================
@@ -202,8 +382,12 @@ export function generateAgentTypescriptProject(config) {
202
382
  files['.env.example'] = generateEnvExample(config);
203
383
  files['.gitignore'] = generateGitignore();
204
384
  files['.trikhub/config.json'] = generateTrikhubConfig();
385
+ files['README.md'] = generateReadme(config);
205
386
  files['src/agent.ts'] = generateAgentTs(config);
206
387
  files['src/cli.ts'] = generateCliTs();
388
+ if (config.channels === 'cli+telegram') {
389
+ files['src/telegram.ts'] = generateTelegramTs();
390
+ }
207
391
  return files;
208
392
  }
209
393
  //# sourceMappingURL=agent-typescript.js.map