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>`
|
|
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-
|
|
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
|
-
|
|
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:
|
|
16
|
-
*
|
|
17
|
-
*
|
|
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,
|
|
16
|
+
export { RenderEvent, StreamInput, streamAgent, toAgentStream };
|
package/dist/deepagents/index.js
CHANGED
|
@@ -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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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-
|
|
2
|
-
export { b as AgentStreamContext, R as RenderEvent, S as StreamInput } from './interfaces-
|
|
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
|
|
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 =
|
|
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