telegram-agent-kit 0.1.0 → 0.3.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 CHANGED
@@ -147,7 +147,7 @@ You implement these; the kit drives them.
147
147
  | Interface | Shape | Role |
148
148
  | -------------- | --------------------------------------------------------------------- | ---- |
149
149
  | `BotClient` | `sendMessage`, `sendRichMessage`, `sendPhoto`, `sendChatAction`, `sendMessageDraft`, `sendRichMessageDraft` | Raw transport. Each throws `TelegramApiError` on a Bot API error. |
150
- | `AgentStream` | `(input, { threadId, signal }) => AsyncIterable<RenderEvent>` | Your agent. `threadId` **must** reach it so the checkpointer writes to the snapshotted thread. |
150
+ | `AgentStream` | `(input, { threadId, signal, configurable }) => AsyncIterable<RenderEvent>` | Your agent. `threadId` **must** reach it so the checkpointer writes to the snapshotted thread. `configurable` is an optional pass-through bag forwarded verbatim from `runTelegramTurn`'s `configurable` option. |
151
151
  | `Checkpointer` | `{ snapshot(threadId), rollback(threadId, id) }` | Per-thread snapshot/rollback for clean recovery on a failed turn. |
152
152
  | `ThreadStore` | `{ resolve(chatKey, now), touch(chatKey, now) }` | Maps `{ chatId, agentId }` to a thread id (so two bots over one chat id don't collide). |
153
153
 
@@ -175,6 +175,8 @@ appends `token` text to the live draft and treats an `error` event as a rollback
175
175
  **Bridge**
176
176
 
177
177
  - `runTelegramTurn(opts)` — orchestrate one turn. Never throws out; every failure is caught and logged.
178
+ Accepts an optional `configurable` bag forwarded to your `AgentStream` as `context.configurable`,
179
+ for passing per-turn data (e.g. `pendingImages`) to the agent without widening the core input type.
178
180
  - `sendReply(client, chatId, reply, opts, signal?)` / `sendText(...)` — the send path on its own.
179
181
  - Types: `BotClient`, `AgentStream`, `Checkpointer`, `ThreadStore`, `RenderEvent`, `ChatKey`, `Logger`.
180
182
 
@@ -186,6 +188,10 @@ appends `token` text to the live draft and treats an `error` event as a rollback
186
188
  ### Optional entry — `telegram-agent-kit/deepagents`
187
189
 
188
190
  - `toAgentStream(agent)` → `AgentStream` — adapts a deepagents/langgraph agent to the kit's contract.
191
+ The `context.configurable` bag is merged into the LangGraph `RunnableConfig`, but the reserved keys
192
+ `thread_id`, `thread_ts`, `checkpoint_id`, `checkpoint_ns`, `checkpoint_map`, and `run_id` — plus any
193
+ `__pregel_*` LangGraph internal-execution key — are stripped so the kit retains full control over
194
+ checkpoint routing and execution.
189
195
  - `streamAgent(agent, input, config, signal?)` — lower-level event stream if you need direct control.
190
196
 
191
197
  > `@langchain/core` and `deepagents` are **type-only, optional** peers. The built
@@ -1,20 +1,16 @@
1
- import { R as RenderEvent, A as AgentStream } from '../interfaces-BRu3W_FZ.js';
1
+ import { S as StreamInput, R as RenderEvent, A as AgentStream } from '../interfaces-DhF4n199.js';
2
2
  import { RunnableConfig } from '@langchain/core/runnables';
3
3
  import { createDeepAgent } from 'deepagents';
4
4
 
5
5
  type Agent$1 = ReturnType<typeof createDeepAgent>;
6
- type StreamAgentInput = {
7
- messages: Array<{
8
- role: 'user';
9
- content: string;
10
- }>;
11
- };
12
- declare function streamAgent(agent: Agent$1, input: StreamAgentInput, config: RunnableConfig, signal?: AbortSignal): AsyncIterable<RenderEvent>;
6
+ declare function streamAgent(agent: Agent$1, input: StreamInput, config: RunnableConfig, signal?: AbortSignal): AsyncIterable<RenderEvent>;
13
7
 
14
8
  type Agent = Parameters<typeof streamAgent>[0];
15
- /** Adapt a deepagents agent to the kit's runtime-agnostic AgentStream: build
16
- * the langgraph config from context.threadId, forward the signal. This is the
17
- * ONLY place the langgraph config shape lives. */
9
+ /** Adapt a deepagents agent to the kit's runtime-agnostic AgentStream: merge the
10
+ * caller's `configurable` bag (with reserved checkpoint-routing keys stripped)
11
+ * under the kit-owned `thread_id`, and forward the signal. The kit's `thread_id`
12
+ * is spread last so it always wins, even if stripping ever misses a key. This is
13
+ * the ONLY place the langgraph config shape lives. */
18
14
  declare function toAgentStream(agent: Agent): AgentStream;
19
15
 
20
- export { RenderEvent, type StreamAgentInput, streamAgent, toAgentStream };
16
+ export { RenderEvent, StreamInput, streamAgent, toAgentStream };
@@ -8,20 +8,7 @@ function extractText(content) {
8
8
  }
9
9
  return "";
10
10
  }
11
- function extractToolError(output) {
12
- if (typeof output !== "object" || output === null) return void 0;
13
- const o = output;
14
- if (o.status !== "error") return void 0;
15
- const c = o.content;
16
- if (typeof c === "string") return c;
17
- try {
18
- return JSON.stringify(c);
19
- } catch {
20
- return String(c);
21
- }
22
- }
23
11
  async function* streamAgent(agent, input, config, signal) {
24
- const toolStart = /* @__PURE__ */ new Map();
25
12
  const iter = agent.streamEvents(input, {
26
13
  ...config,
27
14
  signal,
@@ -33,24 +20,6 @@ async function* streamAgent(agent, input, config, signal) {
33
20
  if (ev.metadata?.langgraph_node !== "model_request") continue;
34
21
  const text = extractText(ev.data?.chunk?.content);
35
22
  if (text) yield { type: "token", text };
36
- } else if (ev.event === "on_tool_start") {
37
- toolStart.set(ev.run_id, Date.now());
38
- yield {
39
- type: "tool_start",
40
- id: ev.run_id,
41
- name: ev.name ?? "unknown",
42
- args: ev.data?.input
43
- };
44
- } else if (ev.event === "on_tool_end" || ev.event === "on_tool_error") {
45
- const startedAt = toolStart.get(ev.run_id) ?? Date.now();
46
- toolStart.delete(ev.run_id);
47
- const error = ev.event === "on_tool_error" ? ev.data?.error instanceof Error ? ev.data.error.message : String(ev.data?.error ?? "tool error") : extractToolError(ev.data?.output);
48
- yield {
49
- type: "tool_end",
50
- id: ev.run_id,
51
- durationMs: Date.now() - startedAt,
52
- ...error !== void 0 ? { error } : {}
53
- };
54
23
  }
55
24
  }
56
25
  } catch (err) {
@@ -62,14 +31,38 @@ async function* streamAgent(agent, input, config, signal) {
62
31
  }
63
32
 
64
33
  // src/deepagents/to-agent-stream.ts
65
- function toAgentStream(agent) {
66
- return (input, context) => streamAgent(
67
- agent,
68
- input,
69
- { configurable: { thread_id: context.threadId } },
70
- context.signal
34
+ var RESERVED = /* @__PURE__ */ new Set([
35
+ "thread_id",
36
+ // Legacy alias for `checkpoint_id`: the installed @langchain/langgraph-checkpoint
37
+ // still resolves it via getCheckpointId() (`checkpoint_id || thread_ts`), so a
38
+ // caller could resume from a hand-picked checkpoint through this key alone even
39
+ // with `checkpoint_id` stripped. Strip it too.
40
+ "thread_ts",
41
+ "checkpoint_id",
42
+ "checkpoint_ns",
43
+ "checkpoint_map",
44
+ "run_id"
45
+ ]);
46
+ var RESERVED_PREFIX = "__pregel_";
47
+ function stripReservedKeys(configurable) {
48
+ return Object.fromEntries(
49
+ Object.entries(configurable).filter(
50
+ ([k]) => !RESERVED.has(k) && !k.startsWith(RESERVED_PREFIX)
51
+ )
71
52
  );
72
53
  }
54
+ function toAgentStream(agent) {
55
+ return (input, context) => {
56
+ const extra = context.configurable ?? {};
57
+ const safe = stripReservedKeys(extra);
58
+ return streamAgent(
59
+ agent,
60
+ input,
61
+ { configurable: { ...safe, thread_id: context.threadId } },
62
+ context.signal
63
+ );
64
+ };
65
+ }
73
66
  export {
74
67
  streamAgent,
75
68
  toAgentStream
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { B as BotClient, L as Logger, C as ChatKey, A as AgentStream, a as Checkpointer, T as ThreadStore } from './interfaces-BRu3W_FZ.js';
2
- export { b as AgentStreamContext, R as RenderEvent, S as StreamInput } from './interfaces-BRu3W_FZ.js';
1
+ import { B as BotClient, L as Logger, C as ChatKey, A as AgentStream, a as Checkpointer, T as ThreadStore } from './interfaces-DhF4n199.js';
2
+ export { b as AgentStreamContext, R as RenderEvent, S as StreamInput } from './interfaces-DhF4n199.js';
3
3
 
4
4
  type SendOpts = {
5
5
  rich: boolean;
@@ -76,8 +76,8 @@ type RunTelegramTurnOpts = {
76
76
  beforeTurn?: (ctx: TurnContext) => void | Promise<void>;
77
77
  afterTurn?: (ctx: TurnContext) => void | Promise<void>;
78
78
  };
79
- makeDraftStreamer?: (deps: DraftStreamerDeps) => DraftStreamer;
80
79
  draftConstants?: Partial<DraftConstants>;
80
+ configurable?: Record<string, unknown>;
81
81
  };
82
82
  declare function runTelegramTurn(opts: RunTelegramTurnOpts): Promise<void>;
83
83
 
package/dist/index.js CHANGED
@@ -170,7 +170,7 @@ function renderLinks(text, autoClose) {
170
170
  rest = rest.slice(m.index + m.length);
171
171
  }
172
172
  }
173
- function renderCode(text, autoClose) {
173
+ function renderInline(text, autoClose) {
174
174
  let out = "";
175
175
  let rest = text;
176
176
  for (; ; ) {
@@ -193,9 +193,6 @@ function renderCode(text, autoClose) {
193
193
  rest = rest.slice(close + 1);
194
194
  }
195
195
  }
196
- function renderInline(line, autoClose) {
197
- return renderCode(line, autoClose);
198
- }
199
196
  var FENCE_OPEN_RE = /^(`{3,}|~{3,})\s*(.*)$/;
200
197
  var TICK_CLOSE_RE = /^`{3,}\s*$/;
201
198
  var TILDE_CLOSE_RE = /^~{3,}\s*$/;
@@ -691,7 +688,6 @@ var NOOP_LOG = { warn: () => {
691
688
  async function runTelegramTurn(opts) {
692
689
  const now = opts.now ?? (() => Date.now());
693
690
  const log = opts.log ?? NOOP_LOG;
694
- const makeDraftStreamer = opts.makeDraftStreamer ?? createDraftStreamer;
695
691
  const ctx = { chatKey: opts.chatKey, userText: opts.userText };
696
692
  let rollback = null;
697
693
  let turnCompleted = false;
@@ -718,7 +714,7 @@ async function runTelegramTurn(opts) {
718
714
  const threadId = await opts.threadStore.resolve(opts.chatKey, now());
719
715
  const checkpointId = await opts.checkpointer.snapshot(threadId);
720
716
  rollback = { threadId, checkpointId };
721
- draft = makeDraftStreamer({
717
+ draft = createDraftStreamer({
722
718
  client: opts.client,
723
719
  chatId: opts.chatKey.chatId,
724
720
  draftId: opts.draftId,
@@ -731,7 +727,7 @@ async function runTelegramTurn(opts) {
731
727
  let errored = false;
732
728
  for await (const ev of opts.agentStream(
733
729
  { messages: [{ role: "user", content: opts.userText }] },
734
- { threadId, signal: opts.signal }
730
+ { threadId, signal: opts.signal, configurable: opts.configurable }
735
731
  )) {
736
732
  if (ev.type === "token") {
737
733
  reply += ev.text;
@@ -5,7 +5,6 @@ type ChatKey = {
5
5
  type Logger = {
6
6
  warn(msg: string, data?: unknown): void;
7
7
  error(msg: string, data?: unknown): void;
8
- info?(msg: string, data?: unknown): void;
9
8
  };
10
9
  /** Raw Bot API transport primitives — one HTTP call each, NO chunking /
11
10
  * rendering / fallback (the kit owns those). Each throws TelegramApiError
@@ -44,16 +43,6 @@ type BotClient = {
44
43
  type RenderEvent = {
45
44
  type: 'token';
46
45
  text: string;
47
- } | {
48
- type: 'tool_start';
49
- id: string;
50
- name: string;
51
- args: unknown;
52
- } | {
53
- type: 'tool_end';
54
- id: string;
55
- durationMs: number;
56
- error?: string;
57
46
  } | {
58
47
  type: 'error';
59
48
  message: string;
@@ -67,6 +56,7 @@ type StreamInput = {
67
56
  type AgentStreamContext = {
68
57
  threadId: string;
69
58
  signal?: AbortSignal;
59
+ configurable?: Record<string, unknown>;
70
60
  };
71
61
  type AgentStream = (input: StreamInput, context: AgentStreamContext) => AsyncIterable<RenderEvent>;
72
62
  type Checkpointer = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "telegram-agent-kit",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Render markdown to Telegram, stream agent replies into live drafts, and drive a snapshot/rollback turn-loop — runtime-agnostic.",
5
5
  "type": "module",
6
6
  "license": "MIT",