@dreb/telegram 2.0.6 → 2.1.0
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/README.md +2 -1
- package/dist/commands/core.d.ts.map +1 -1
- package/dist/commands/core.js +2 -1
- package/dist/commands/core.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -76,7 +76,8 @@ systemctl --user enable --now dreb-telegram
|
|
|
76
76
|
|
|
77
77
|
### Session
|
|
78
78
|
- `/start` — Help & command list
|
|
79
|
-
- `/new` — Start fresh session
|
|
79
|
+
- `/new` — Start fresh session (preserves current working directory)
|
|
80
|
+
- `/new <path>` — Start fresh session in the specified directory
|
|
80
81
|
- `/sessions` — List recent sessions
|
|
81
82
|
- `/resume <id>` — Resume by session ID prefix
|
|
82
83
|
- `/recent [N]` — Resend last N assistant messages
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/commands/core.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C,wBAAsB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/commands/core.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C,wBAAsB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB1D;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BjG;AAED,wBAAsB,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9F;AAED,wBAAsB,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB5F;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAY1F;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ5E","sourcesContent":["/**\n * Core slash commands: /start, /status, /cwd, /new, /stop, /restart\n */\n\nimport { execSync } from \"node:child_process\";\nimport { existsSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { resolve } from \"node:path\";\nimport type { Api, Context } from \"grammy\";\nimport type { Config } from \"../config.js\";\nimport type { UserState } from \"../types.js\";\nimport { log, safeSend } from \"../util/telegram.js\";\n\nexport async function cmdStart(ctx: Context): Promise<void> {\n\tawait ctx.reply(\n\t\t\"🤖 *dreb Telegram*\\n\\n\" +\n\t\t\t\"Send me a message and I'll forward it to dreb.\\n\\n\" +\n\t\t\t\"*Session:*\\n\" +\n\t\t\t\"/new — Start a fresh session (keeps current directory)\\n\" +\n\t\t\t\"/new <path> — Start a fresh session in a different directory\\n\" +\n\t\t\t\"/sessions — List recent sessions\\n\" +\n\t\t\t\"/resume <id> — Resume a session\\n\" +\n\t\t\t\"/recent \\\\[N\\\\] — Resend last N messages\\n\\n\" +\n\t\t\t\"*Agent:*\\n\" +\n\t\t\t\"/status — Connection info\\n\" +\n\t\t\t\"/cwd — Working directory\\n\" +\n\t\t\t\"/stats — Token usage & cost\\n\" +\n\t\t\t\"/compact — Compact context\\n\" +\n\t\t\t\"/agents — Background subagents\\n\" +\n\t\t\t\"/model \\\\[pattern\\\\] — View/switch model\\n\" +\n\t\t\t\"/thinking \\\\[level\\\\] — View/set thinking\\n\" +\n\t\t\t\"/skills — List available skills\\n\\n\" +\n\t\t\t\"*Control:*\\n\" +\n\t\t\t\"/stop — Interrupt current task\\n\" +\n\t\t\t\"/restart — Restart the bot\",\n\t\t{ parse_mode: \"Markdown\" },\n\t);\n}\n\nexport async function cmdStatus(ctx: Context, config: Config, userState: UserState): Promise<void> {\n\tconst chatId = ctx.chat!.id;\n\tconst bridge = userState.bridge;\n\n\tlet version = \"unknown\";\n\tlet model = \"none\";\n\ttry {\n\t\tif (bridge?.isAlive) {\n\t\t\tversion = await bridge.getVersion();\n\t\t\tconst state = await bridge.getState();\n\t\t\tif (state?.model) model = `${state.model.provider}/${state.model.id}`;\n\t\t}\n\t} catch (e) {\n\t\tlog(`[CMD] /status error: ${e}`);\n\t}\n\n\tconst lines = [\n\t\tbridge?.isAlive ? \"✅ Connected\" : \"⚠️ Not connected (will start on next message)\",\n\t\t`📁 Working dir: \\`${config.workingDir}\\``,\n\t\t`🔧 dreb ${version}`,\n\t\t`🧠 Model: ${model}`,\n\t];\n\n\tif (bridge?.sessionId) {\n\t\tlines.push(`📂 Session: \\`${bridge.sessionId.slice(0, 8)}...\\``);\n\t}\n\n\tawait safeSend(ctx.api, chatId, lines.join(\"\\n\"));\n}\n\nexport async function cmdCwd(ctx: Context, config: Config, userState: UserState): Promise<void> {\n\tconst cwd = userState.effectiveCwd ?? config.workingDir;\n\tawait safeSend(ctx.api, ctx.chat!.id, `📁 Working directory: \\`${cwd}\\``);\n}\n\nexport async function cmdNew(ctx: Context, userState: UserState, args: string): Promise<void> {\n\tconst pathArg = args.trim();\n\n\tif (pathArg) {\n\t\t// Resolve path (expand ~ and make absolute)\n\t\tconst expanded = pathArg.startsWith(\"~\") ? pathArg.replace(\"~\", homedir()) : pathArg;\n\t\tconst resolved = resolve(expanded);\n\n\t\tif (!existsSync(resolved)) {\n\t\t\tawait safeSend(ctx.api, ctx.chat!.id, `❌ Directory not found: \\`${resolved}\\``);\n\t\t\treturn;\n\t\t}\n\t\tif (!statSync(resolved).isDirectory()) {\n\t\t\tawait safeSend(ctx.api, ctx.chat!.id, `❌ Not a directory: \\`${resolved}\\``);\n\t\t\treturn;\n\t\t}\n\n\t\tuserState.newSessionFlag = true;\n\t\tuserState.newSessionCwd = resolved;\n\t\tawait ctx.reply(`🆕 Next message will start a fresh session in \\`${resolved}\\``);\n\t} else {\n\t\tuserState.newSessionFlag = true;\n\t\tuserState.newSessionCwd = null;\n\t\tawait ctx.reply(\"🆕 Next message will start a fresh session.\");\n\t}\n}\n\nexport async function cmdStop(ctx: Context, _api: Api, userState: UserState): Promise<void> {\n\tuserState.stopRequested = true;\n\n\t// Abort current agent activity — like pressing Esc in the TUI.\n\t// This stops the agent, not the bridge. Session stays connected.\n\tif (userState.bridge?.isAlive) {\n\t\tawait userState.bridge.abort();\n\t}\n\n\tconst parts: string[] = [];\n\tif (userState.bridge?.isStreaming || userState.promptInFlight) parts.push(\"interrupted current task\");\n\tawait ctx.reply(parts.length > 0 ? `🛑 Stopped — ${parts.join(\", \")}.` : \"🛑 Stopped.\");\n}\n\nexport async function cmdRestart(ctx: Context, config: Config): Promise<void> {\n\tawait ctx.reply(\"🔄 Restarting...\");\n\tlog(\"[CMD] /restart — triggering systemctl restart\");\n\ttry {\n\t\texecSync(`systemctl --user restart ${config.serviceName}`, { timeout: 5000 });\n\t} catch {\n\t\t// Process will be killed by systemd restart\n\t}\n}\n"]}
|
package/dist/commands/core.js
CHANGED
|
@@ -10,7 +10,8 @@ export async function cmdStart(ctx) {
|
|
|
10
10
|
await ctx.reply("🤖 *dreb Telegram*\n\n" +
|
|
11
11
|
"Send me a message and I'll forward it to dreb.\n\n" +
|
|
12
12
|
"*Session:*\n" +
|
|
13
|
-
"/new
|
|
13
|
+
"/new — Start a fresh session (keeps current directory)\n" +
|
|
14
|
+
"/new <path> — Start a fresh session in a different directory\n" +
|
|
14
15
|
"/sessions — List recent sessions\n" +
|
|
15
16
|
"/resume <id> — Resume a session\n" +
|
|
16
17
|
"/recent \\[N\\] — Resend last N messages\n\n" +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/commands/core.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,GAAY,EAAiB;IAC3D,MAAM,GAAG,CAAC,KAAK,CACd,0BAAuB;QACtB,oDAAoD;QACpD,cAAc;QACd,
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/commands/core.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Core slash commands: /start, /status, /cwd, /new, /stop, /restart\n */\n\nimport { execSync } from \"node:child_process\";\nimport { existsSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { resolve } from \"node:path\";\nimport type { Api, Context } from \"grammy\";\nimport type { Config } from \"../config.js\";\nimport type { UserState } from \"../types.js\";\nimport { log, safeSend } from \"../util/telegram.js\";\n\nexport async function cmdStart(ctx: Context): Promise<void> {\n\tawait ctx.reply(\n\t\t\"🤖 *dreb Telegram*\\n\\n\" +\n\t\t\t\"Send me a message and I'll forward it to dreb.\\n\\n\" +\n\t\t\t\"*Session:*\\n\" +\n\t\t\t\"/new — Start a fresh session (keeps current directory)\\n\" +\n\t\t\t\"/new <path> — Start a fresh session in a different directory\\n\" +\n\t\t\t\"/sessions — List recent sessions\\n\" +\n\t\t\t\"/resume <id> — Resume a session\\n\" +\n\t\t\t\"/recent \\\\[N\\\\] — Resend last N messages\\n\\n\" +\n\t\t\t\"*Agent:*\\n\" +\n\t\t\t\"/status — Connection info\\n\" +\n\t\t\t\"/cwd — Working directory\\n\" +\n\t\t\t\"/stats — Token usage & cost\\n\" +\n\t\t\t\"/compact — Compact context\\n\" +\n\t\t\t\"/agents — Background subagents\\n\" +\n\t\t\t\"/model \\\\[pattern\\\\] — View/switch model\\n\" +\n\t\t\t\"/thinking \\\\[level\\\\] — View/set thinking\\n\" +\n\t\t\t\"/skills — List available skills\\n\\n\" +\n\t\t\t\"*Control:*\\n\" +\n\t\t\t\"/stop — Interrupt current task\\n\" +\n\t\t\t\"/restart — Restart the bot\",\n\t\t{ parse_mode: \"Markdown\" },\n\t);\n}\n\nexport async function cmdStatus(ctx: Context, config: Config, userState: UserState): Promise<void> {\n\tconst chatId = ctx.chat!.id;\n\tconst bridge = userState.bridge;\n\n\tlet version = \"unknown\";\n\tlet model = \"none\";\n\ttry {\n\t\tif (bridge?.isAlive) {\n\t\t\tversion = await bridge.getVersion();\n\t\t\tconst state = await bridge.getState();\n\t\t\tif (state?.model) model = `${state.model.provider}/${state.model.id}`;\n\t\t}\n\t} catch (e) {\n\t\tlog(`[CMD] /status error: ${e}`);\n\t}\n\n\tconst lines = [\n\t\tbridge?.isAlive ? \"✅ Connected\" : \"⚠️ Not connected (will start on next message)\",\n\t\t`📁 Working dir: \\`${config.workingDir}\\``,\n\t\t`🔧 dreb ${version}`,\n\t\t`🧠 Model: ${model}`,\n\t];\n\n\tif (bridge?.sessionId) {\n\t\tlines.push(`📂 Session: \\`${bridge.sessionId.slice(0, 8)}...\\``);\n\t}\n\n\tawait safeSend(ctx.api, chatId, lines.join(\"\\n\"));\n}\n\nexport async function cmdCwd(ctx: Context, config: Config, userState: UserState): Promise<void> {\n\tconst cwd = userState.effectiveCwd ?? config.workingDir;\n\tawait safeSend(ctx.api, ctx.chat!.id, `📁 Working directory: \\`${cwd}\\``);\n}\n\nexport async function cmdNew(ctx: Context, userState: UserState, args: string): Promise<void> {\n\tconst pathArg = args.trim();\n\n\tif (pathArg) {\n\t\t// Resolve path (expand ~ and make absolute)\n\t\tconst expanded = pathArg.startsWith(\"~\") ? pathArg.replace(\"~\", homedir()) : pathArg;\n\t\tconst resolved = resolve(expanded);\n\n\t\tif (!existsSync(resolved)) {\n\t\t\tawait safeSend(ctx.api, ctx.chat!.id, `❌ Directory not found: \\`${resolved}\\``);\n\t\t\treturn;\n\t\t}\n\t\tif (!statSync(resolved).isDirectory()) {\n\t\t\tawait safeSend(ctx.api, ctx.chat!.id, `❌ Not a directory: \\`${resolved}\\``);\n\t\t\treturn;\n\t\t}\n\n\t\tuserState.newSessionFlag = true;\n\t\tuserState.newSessionCwd = resolved;\n\t\tawait ctx.reply(`🆕 Next message will start a fresh session in \\`${resolved}\\``);\n\t} else {\n\t\tuserState.newSessionFlag = true;\n\t\tuserState.newSessionCwd = null;\n\t\tawait ctx.reply(\"🆕 Next message will start a fresh session.\");\n\t}\n}\n\nexport async function cmdStop(ctx: Context, _api: Api, userState: UserState): Promise<void> {\n\tuserState.stopRequested = true;\n\n\t// Abort current agent activity — like pressing Esc in the TUI.\n\t// This stops the agent, not the bridge. Session stays connected.\n\tif (userState.bridge?.isAlive) {\n\t\tawait userState.bridge.abort();\n\t}\n\n\tconst parts: string[] = [];\n\tif (userState.bridge?.isStreaming || userState.promptInFlight) parts.push(\"interrupted current task\");\n\tawait ctx.reply(parts.length > 0 ? `🛑 Stopped — ${parts.join(\", \")}.` : \"🛑 Stopped.\");\n}\n\nexport async function cmdRestart(ctx: Context, config: Config): Promise<void> {\n\tawait ctx.reply(\"🔄 Restarting...\");\n\tlog(\"[CMD] /restart — triggering systemctl restart\");\n\ttry {\n\t\texecSync(`systemctl --user restart ${config.serviceName}`, { timeout: 5000 });\n\t} catch {\n\t\t// Process will be killed by systemd restart\n\t}\n}\n"]}
|