@theokit/cli 0.1.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.
- package/CHANGELOG.md +84 -0
- package/README.md +126 -0
- package/dist/bin/theokit.cjs +1557 -0
- package/dist/bin/theokit.cjs.map +1 -0
- package/dist/bin/theokit.js +1531 -0
- package/dist/bin/theokit.js.map +1 -0
- package/dist/index.cjs +1552 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +28 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +1524 -0
- package/dist/index.js.map +1 -0
- package/package.json +63 -0
- package/templates/minimal/.env.example +14 -0
- package/templates/minimal/README.md +29 -0
- package/templates/minimal/package.json +21 -0
- package/templates/minimal/src/index.ts +38 -0
- package/templates/minimal/tsconfig.json +12 -0
- package/templates/ollama-local/.env.example +16 -0
- package/templates/ollama-local/README.md +46 -0
- package/templates/ollama-local/package.json +21 -0
- package/templates/ollama-local/src/index.ts +51 -0
- package/templates/ollama-local/tsconfig.json +12 -0
- package/templates/telegram-bot/.env.example +15 -0
- package/templates/telegram-bot/README.md +35 -0
- package/templates/telegram-bot/package.json +24 -0
- package/templates/telegram-bot/src/index.ts +66 -0
- package/templates/telegram-bot/tsconfig.json +12 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {{projectName}} — 100% local agent via Ollama (ADR D182).
|
|
3
|
+
*
|
|
4
|
+
* Zero remote API keys required. Boots Ollama (must be running locally),
|
|
5
|
+
* pre-warms the model, sends a prompt, streams the reply.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Agent } from "@theokit/sdk";
|
|
9
|
+
|
|
10
|
+
const OLLAMA_HOST = process.env.OLLAMA_HOST ?? "http://localhost:11434";
|
|
11
|
+
const MODEL = process.env.OLLAMA_MODEL ?? "ollama/llama3.2:3b";
|
|
12
|
+
|
|
13
|
+
async function streamAssistantText(
|
|
14
|
+
run: Awaited<ReturnType<Awaited<ReturnType<typeof Agent.create>>["send"]>>,
|
|
15
|
+
): Promise<void> {
|
|
16
|
+
for await (const event of run.stream()) {
|
|
17
|
+
if (event.type !== "assistant") continue;
|
|
18
|
+
for (const part of event.message.content) {
|
|
19
|
+
if (part.type === "text") process.stdout.write(part.text);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function main(): Promise<void> {
|
|
25
|
+
const agent = await Agent.create({
|
|
26
|
+
apiKey: process.env.THEOKIT_API_KEY ?? "local",
|
|
27
|
+
model: { id: MODEL },
|
|
28
|
+
local: { cwd: process.cwd() },
|
|
29
|
+
systemPrompt:
|
|
30
|
+
"You are a concise assistant. Respond in one or two short sentences. No greetings.",
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
console.log(`Agent: ${agent.agentId}`);
|
|
34
|
+
console.log(`Model: ${MODEL}`);
|
|
35
|
+
console.log(`Host: ${OLLAMA_HOST}\n`);
|
|
36
|
+
|
|
37
|
+
const run = await agent.send("Explain what dependency injection is, in one sentence.");
|
|
38
|
+
await streamAssistantText(run);
|
|
39
|
+
await run.wait();
|
|
40
|
+
process.stdout.write("\n");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
main().catch((cause) => {
|
|
44
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
45
|
+
console.error("ollama agent failed:", message);
|
|
46
|
+
if (/ollama_unreachable|ECONNREFUSED/.test(message)) {
|
|
47
|
+
console.error("\nHint: run `ollama serve` to start the local runtime,");
|
|
48
|
+
console.error("or set OLLAMA_HOST to point at a remote Ollama box.");
|
|
49
|
+
}
|
|
50
|
+
process.exit(1);
|
|
51
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Telegram bot token from @BotFather (https://t.me/BotFather)
|
|
2
|
+
# 1. /start → /newbot → follow prompts → copy the token here.
|
|
3
|
+
TELEGRAM_BOT_TOKEN=
|
|
4
|
+
|
|
5
|
+
# Provider key — pick ONE.
|
|
6
|
+
# ANTHROPIC_API_KEY=sk-ant-...
|
|
7
|
+
# OPENAI_API_KEY=sk-...
|
|
8
|
+
# OPENROUTER_API_KEY=sk-or-...
|
|
9
|
+
|
|
10
|
+
# THEOKIT_API_KEY — any non-empty string. Default: "local".
|
|
11
|
+
THEOKIT_API_KEY=local
|
|
12
|
+
|
|
13
|
+
# AGENT_MODEL — override the default (anthropic/claude-3-5-sonnet-latest).
|
|
14
|
+
# For local Ollama:
|
|
15
|
+
# AGENT_MODEL=ollama/llama3.2:3b
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# {{projectName}}
|
|
2
|
+
|
|
3
|
+
A Telegram bot powered by `@theokit/sdk` + `@theokit/gateway` — scaffolded
|
|
4
|
+
by `theokit init --template telegram-bot`.
|
|
5
|
+
|
|
6
|
+
## Setup
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
# 1. Create a bot via @BotFather: https://t.me/BotFather
|
|
10
|
+
# /start → /newbot → name it → copy the token.
|
|
11
|
+
# 2. Configure:
|
|
12
|
+
cp .env.example .env
|
|
13
|
+
# Edit .env: set TELEGRAM_BOT_TOKEN and ONE of the provider API keys.
|
|
14
|
+
|
|
15
|
+
# 3. Install + run:
|
|
16
|
+
pnpm install
|
|
17
|
+
pnpm dev
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Then DM your bot in Telegram. Every message gets streamed through the agent.
|
|
21
|
+
|
|
22
|
+
## What this does
|
|
23
|
+
|
|
24
|
+
- `GatewayRunner` + `TelegramAdapter` handle the platform plumbing.
|
|
25
|
+
- `createAgentFactory` keeps one persistent agent per chat (memory + state
|
|
26
|
+
preserved across turns).
|
|
27
|
+
- Each inbound message → `agent.send` → reply back via `ctx.reply`.
|
|
28
|
+
|
|
29
|
+
## Customize
|
|
30
|
+
|
|
31
|
+
- Switch model: `AGENT_MODEL=ollama/llama3.2:3b` for local Ollama.
|
|
32
|
+
- Add custom tools: import `defineTool` from `@theokit/sdk` and pass via
|
|
33
|
+
`createAgentFactory({ tools: [...] })`.
|
|
34
|
+
- Slash commands: `runner.command("name", handler)` — see
|
|
35
|
+
`@theokit/gateway` docs.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{projectName}}",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "tsx --env-file=.env src/index.ts",
|
|
8
|
+
"start": "tsx --env-file=.env src/index.ts"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@theokit/sdk": "^{{sdkVersion}}",
|
|
12
|
+
"@theokit/gateway": "^{{sdkVersion}}",
|
|
13
|
+
"@theokit/gateway-telegram": "^{{sdkVersion}}",
|
|
14
|
+
"grammy": "^1.30.0",
|
|
15
|
+
"zod": "^3.25.0"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"tsx": "^4.19.0",
|
|
19
|
+
"typescript": "^5.8.0"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=22.12.0"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {{projectName}} — a Telegram bot powered by @theokit/sdk + @theokit/gateway.
|
|
3
|
+
*
|
|
4
|
+
* Boots a grammy bot, routes every inbound message through Agent.send,
|
|
5
|
+
* streams the reply back to Telegram.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { GatewayRunner } from "@theokit/gateway";
|
|
9
|
+
import { TelegramAdapter } from "@theokit/gateway-telegram";
|
|
10
|
+
import { createAgentFactory } from "@theokit/sdk";
|
|
11
|
+
import { Bot } from "grammy";
|
|
12
|
+
|
|
13
|
+
const TELEGRAM_BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN;
|
|
14
|
+
if (TELEGRAM_BOT_TOKEN === undefined || TELEGRAM_BOT_TOKEN.length === 0) {
|
|
15
|
+
console.error(
|
|
16
|
+
"ABORT: TELEGRAM_BOT_TOKEN missing. Create a bot via @BotFather and add it to .env.",
|
|
17
|
+
);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const API_KEY = process.env.THEOKIT_API_KEY ?? "local";
|
|
22
|
+
const MODEL = process.env.AGENT_MODEL ?? "anthropic/claude-3-5-sonnet-latest";
|
|
23
|
+
|
|
24
|
+
const factory = createAgentFactory({
|
|
25
|
+
apiKey: API_KEY,
|
|
26
|
+
model: { id: MODEL },
|
|
27
|
+
local: { cwd: process.cwd() },
|
|
28
|
+
systemPrompt: "You are a concise Telegram assistant. Reply in one or two sentences.",
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const bot = new Bot(TELEGRAM_BOT_TOKEN);
|
|
32
|
+
const adapter = new TelegramAdapter({ bot });
|
|
33
|
+
|
|
34
|
+
async function collectReply(
|
|
35
|
+
run: Awaited<ReturnType<Awaited<ReturnType<typeof factory.getOrCreate>>["send"]>>,
|
|
36
|
+
): Promise<string> {
|
|
37
|
+
let reply = "";
|
|
38
|
+
for await (const e of run.stream()) {
|
|
39
|
+
if (e.type !== "assistant") continue;
|
|
40
|
+
for (const part of e.message.content) {
|
|
41
|
+
if (part.type === "text") reply += part.text;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
await run.wait();
|
|
45
|
+
return reply;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const runner = new GatewayRunner({
|
|
49
|
+
adapters: [adapter],
|
|
50
|
+
handler: async (event, ctx) => {
|
|
51
|
+
if (event.text.length === 0) return;
|
|
52
|
+
const agentId = `${event.platform}-dm-${event.sender.id}`;
|
|
53
|
+
const agent = await factory.getOrCreate(agentId);
|
|
54
|
+
const run = await agent.send(event.text);
|
|
55
|
+
const reply = await collectReply(run);
|
|
56
|
+
if (reply.length > 0) await ctx.reply(reply);
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
await runner.start();
|
|
61
|
+
console.log(`Bot started. Send a message in Telegram to your bot.`);
|
|
62
|
+
|
|
63
|
+
process.on("SIGINT", async () => {
|
|
64
|
+
await runner.stop();
|
|
65
|
+
process.exit(0);
|
|
66
|
+
});
|