auggy 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/CHANGELOG.md +96 -0
- package/LICENSE +201 -0
- package/README.md +161 -0
- package/package.json +76 -0
- package/src/agent-card.ts +39 -0
- package/src/agent.ts +283 -0
- package/src/agentmail-client.ts +138 -0
- package/src/augments/bash/index.ts +463 -0
- package/src/augments/bash/skill/SKILL.md +156 -0
- package/src/augments/budgets/budget-store.ts +513 -0
- package/src/augments/budgets/index.ts +134 -0
- package/src/augments/budgets/preamble.ts +93 -0
- package/src/augments/budgets/types.ts +89 -0
- package/src/augments/file-memory/index.ts +71 -0
- package/src/augments/filesystem/index.ts +533 -0
- package/src/augments/filesystem/skill/SKILL.md +142 -0
- package/src/augments/filesystem/skill/references/mount-permissions.md +81 -0
- package/src/augments/layered-memory/extractor/buffer.ts +56 -0
- package/src/augments/layered-memory/extractor/frequency.ts +79 -0
- package/src/augments/layered-memory/extractor/inject-handler.ts +103 -0
- package/src/augments/layered-memory/extractor/parse.ts +75 -0
- package/src/augments/layered-memory/extractor/prompt.md +26 -0
- package/src/augments/layered-memory/index.ts +757 -0
- package/src/augments/layered-memory/skill/SKILL.md +153 -0
- package/src/augments/layered-memory/storage/migrations/README.md +16 -0
- package/src/augments/layered-memory/storage/migrations/supabase-add-fact-fields.sql +9 -0
- package/src/augments/layered-memory/storage/sqlite-store.ts +352 -0
- package/src/augments/layered-memory/storage/supabase-store.ts +263 -0
- package/src/augments/layered-memory/storage/types.ts +98 -0
- package/src/augments/link/index.ts +489 -0
- package/src/augments/link/translate.ts +261 -0
- package/src/augments/notify/adapters/agentmail.ts +70 -0
- package/src/augments/notify/adapters/telegram.ts +60 -0
- package/src/augments/notify/adapters/webhook.ts +55 -0
- package/src/augments/notify/index.ts +284 -0
- package/src/augments/notify/skill/SKILL.md +150 -0
- package/src/augments/org-context/index.ts +721 -0
- package/src/augments/org-context/skill/SKILL.md +96 -0
- package/src/augments/skills/index.ts +103 -0
- package/src/augments/supabase-memory/index.ts +151 -0
- package/src/augments/telegram-transport/index.ts +312 -0
- package/src/augments/telegram-transport/polling.ts +55 -0
- package/src/augments/telegram-transport/webhook.ts +56 -0
- package/src/augments/turn-control/index.ts +61 -0
- package/src/augments/turn-control/skill/SKILL.md +155 -0
- package/src/augments/visitor-auth/email-validation.ts +66 -0
- package/src/augments/visitor-auth/index.ts +779 -0
- package/src/augments/visitor-auth/rate-limiter.ts +90 -0
- package/src/augments/visitor-auth/skill/SKILL.md +55 -0
- package/src/augments/visitor-auth/storage/sqlite-store.ts +398 -0
- package/src/augments/visitor-auth/storage/types.ts +164 -0
- package/src/augments/visitor-auth/types.ts +123 -0
- package/src/augments/visitor-auth/verify-page.ts +179 -0
- package/src/augments/web-fetch/index.ts +331 -0
- package/src/augments/web-fetch/skill/SKILL.md +100 -0
- package/src/cli/agent-index.ts +289 -0
- package/src/cli/augment-catalog.ts +320 -0
- package/src/cli/augment-resolver.ts +597 -0
- package/src/cli/commands/add-skill.ts +194 -0
- package/src/cli/commands/add.ts +87 -0
- package/src/cli/commands/chat.ts +207 -0
- package/src/cli/commands/create.ts +462 -0
- package/src/cli/commands/dev.ts +139 -0
- package/src/cli/commands/eval.ts +180 -0
- package/src/cli/commands/ls.ts +66 -0
- package/src/cli/commands/remove.ts +95 -0
- package/src/cli/commands/restart.ts +40 -0
- package/src/cli/commands/start.ts +123 -0
- package/src/cli/commands/status.ts +104 -0
- package/src/cli/commands/stop.ts +84 -0
- package/src/cli/commands/visitors-revoke.ts +155 -0
- package/src/cli/commands/visitors.ts +101 -0
- package/src/cli/config-parser.ts +1034 -0
- package/src/cli/engine-resolver.ts +68 -0
- package/src/cli/index.ts +178 -0
- package/src/cli/model-picker.ts +89 -0
- package/src/cli/pid-registry.ts +146 -0
- package/src/cli/plist-generator.ts +117 -0
- package/src/cli/resolve-config.ts +56 -0
- package/src/cli/scaffold-skills.ts +158 -0
- package/src/cli/scaffold.ts +291 -0
- package/src/cli/skill-frontmatter.ts +51 -0
- package/src/cli/skill-validator.ts +151 -0
- package/src/cli/types.ts +228 -0
- package/src/cli/yaml-helpers.ts +66 -0
- package/src/engines/_shared/cost.ts +55 -0
- package/src/engines/_shared/schema-normalize.ts +75 -0
- package/src/engines/anthropic/pricing.ts +117 -0
- package/src/engines/anthropic.ts +483 -0
- package/src/engines/openai/pricing.ts +67 -0
- package/src/engines/openai.ts +446 -0
- package/src/engines/openrouter/pricing.ts +83 -0
- package/src/engines/openrouter.ts +185 -0
- package/src/helpers.ts +24 -0
- package/src/http.ts +387 -0
- package/src/index.ts +165 -0
- package/src/kernel/capability-table.ts +172 -0
- package/src/kernel/context-allocator.ts +161 -0
- package/src/kernel/history-manager.ts +198 -0
- package/src/kernel/lifecycle-manager.ts +106 -0
- package/src/kernel/output-validator.ts +35 -0
- package/src/kernel/preamble.ts +23 -0
- package/src/kernel/route-collector.ts +97 -0
- package/src/kernel/timeout.ts +21 -0
- package/src/kernel/tool-selector.ts +47 -0
- package/src/kernel/trace-emitter.ts +66 -0
- package/src/kernel/transport-queue.ts +147 -0
- package/src/kernel/turn-loop.ts +1148 -0
- package/src/memory/context-synthesis.ts +83 -0
- package/src/memory/memory-bus.ts +61 -0
- package/src/memory/registry.ts +80 -0
- package/src/memory/tools.ts +320 -0
- package/src/memory/types.ts +8 -0
- package/src/parts.ts +30 -0
- package/src/scaffold-templates/identity.md +31 -0
- package/src/telegram-client.ts +145 -0
- package/src/tokenizer.ts +14 -0
- package/src/transports/ag-ui-events.ts +253 -0
- package/src/transports/visitor-token.ts +82 -0
- package/src/transports/web-transport.ts +948 -0
- package/src/types.ts +1009 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Telegram bot API client.
|
|
3
|
+
*
|
|
4
|
+
* Used by both `notify`'s telegram adapter and `telegramTransport`. NOT a
|
|
5
|
+
* cross-augment dependency — peer library import only. Mirrors the shared-
|
|
6
|
+
* utility pattern of `src/http.ts` and `src/engines/_shared/cost.ts`.
|
|
7
|
+
*
|
|
8
|
+
* Future bot-API surface (file uploads, editMessageText for streaming-edit
|
|
9
|
+
* replies, reactions, inline keyboards) MUST land here, not be duplicated
|
|
10
|
+
* across notify and telegramTransport.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { HttpClient } from "./http";
|
|
14
|
+
import { createHttpClient } from "./http";
|
|
15
|
+
|
|
16
|
+
export interface SendMessageOptions {
|
|
17
|
+
parseMode?: "Markdown" | "HTML" | "MarkdownV2";
|
|
18
|
+
replyToMessageId?: number;
|
|
19
|
+
disableNotification?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface SendMessageResult {
|
|
23
|
+
messageId: number;
|
|
24
|
+
chatId: number | string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface GetUpdatesOptions {
|
|
28
|
+
offset?: number;
|
|
29
|
+
timeoutSec?: number;
|
|
30
|
+
allowedUpdates?: string[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface SetWebhookOptions {
|
|
34
|
+
allowedUpdates?: string[];
|
|
35
|
+
dropPendingUpdates?: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface TelegramUpdate {
|
|
39
|
+
update_id: number;
|
|
40
|
+
message?: TelegramMessage;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface TelegramMessage {
|
|
44
|
+
message_id: number;
|
|
45
|
+
from?: { id: number; is_bot: boolean; first_name?: string; username?: string };
|
|
46
|
+
chat: { id: number; type: string };
|
|
47
|
+
date: number;
|
|
48
|
+
text?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface TelegramChat {
|
|
52
|
+
id: number;
|
|
53
|
+
type: string;
|
|
54
|
+
title?: string;
|
|
55
|
+
first_name?: string;
|
|
56
|
+
username?: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface TelegramBotClient {
|
|
60
|
+
sendMessage(
|
|
61
|
+
chatId: number | string,
|
|
62
|
+
text: string,
|
|
63
|
+
opts?: SendMessageOptions,
|
|
64
|
+
): Promise<SendMessageResult>;
|
|
65
|
+
getUpdates(opts: GetUpdatesOptions): Promise<TelegramUpdate[]>;
|
|
66
|
+
setWebhook(url: string, secretToken: string, opts?: SetWebhookOptions): Promise<void>;
|
|
67
|
+
deleteWebhook(): Promise<void>;
|
|
68
|
+
getChat(chatId: number | string): Promise<TelegramChat>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface CreateTelegramBotClientOptions {
|
|
72
|
+
botToken: string;
|
|
73
|
+
client?: Pick<HttpClient, "post">;
|
|
74
|
+
baseUrl?: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
interface BotApiResponse<T> {
|
|
78
|
+
ok: boolean;
|
|
79
|
+
result?: T;
|
|
80
|
+
description?: string;
|
|
81
|
+
error_code?: number;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function createTelegramBotClient(opts: CreateTelegramBotClientOptions): TelegramBotClient {
|
|
85
|
+
const baseUrl = opts.baseUrl ?? "https://api.telegram.org";
|
|
86
|
+
const url = (method: string) => `${baseUrl}/bot${opts.botToken}/${method}`;
|
|
87
|
+
const http =
|
|
88
|
+
opts.client ?? createHttpClient({ timeoutMs: 60_000, userAgent: "auggy-telegram/0.1" });
|
|
89
|
+
|
|
90
|
+
async function call<T>(method: string, body: Record<string, unknown>): Promise<T> {
|
|
91
|
+
const res = await http.post(url(method), {
|
|
92
|
+
headers: { "content-type": "application/json" },
|
|
93
|
+
body: JSON.stringify(body),
|
|
94
|
+
});
|
|
95
|
+
let parsed: BotApiResponse<T>;
|
|
96
|
+
try {
|
|
97
|
+
parsed = JSON.parse(res.body) as BotApiResponse<T>;
|
|
98
|
+
} catch {
|
|
99
|
+
throw new Error(`Telegram bot API ${method}: non-JSON response (${res.status})`);
|
|
100
|
+
}
|
|
101
|
+
if (!parsed.ok) {
|
|
102
|
+
throw new Error(
|
|
103
|
+
`Telegram bot API ${method}: ${parsed.description ?? "unknown error"} (${res.status})`,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
return parsed.result as T;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
async sendMessage(chatId, text, sendOpts) {
|
|
111
|
+
const body: Record<string, unknown> = { chat_id: chatId, text };
|
|
112
|
+
if (sendOpts?.parseMode) body.parse_mode = sendOpts.parseMode;
|
|
113
|
+
if (sendOpts?.replyToMessageId != null) body.reply_to_message_id = sendOpts.replyToMessageId;
|
|
114
|
+
if (sendOpts?.disableNotification) body.disable_notification = true;
|
|
115
|
+
const result = await call<{ message_id: number; chat: { id: number | string } }>(
|
|
116
|
+
"sendMessage",
|
|
117
|
+
body,
|
|
118
|
+
);
|
|
119
|
+
return { messageId: result.message_id, chatId: result.chat.id };
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
async getUpdates(getOpts) {
|
|
123
|
+
const body: Record<string, unknown> = {};
|
|
124
|
+
if (getOpts.offset != null) body.offset = getOpts.offset;
|
|
125
|
+
if (getOpts.timeoutSec != null) body.timeout = getOpts.timeoutSec;
|
|
126
|
+
if (getOpts.allowedUpdates) body.allowed_updates = getOpts.allowedUpdates;
|
|
127
|
+
return await call<TelegramUpdate[]>("getUpdates", body);
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
async setWebhook(webhookUrl, secretToken, webhookOpts) {
|
|
131
|
+
const body: Record<string, unknown> = { url: webhookUrl, secret_token: secretToken };
|
|
132
|
+
if (webhookOpts?.allowedUpdates) body.allowed_updates = webhookOpts.allowedUpdates;
|
|
133
|
+
if (webhookOpts?.dropPendingUpdates) body.drop_pending_updates = true;
|
|
134
|
+
await call<true>("setWebhook", body);
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
async deleteWebhook() {
|
|
138
|
+
await call<true>("deleteWebhook", {});
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
async getChat(chatId) {
|
|
142
|
+
return await call<TelegramChat>("getChat", { chat_id: chatId });
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
package/src/tokenizer.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface Tokenizer {
|
|
2
|
+
count(text: string): number;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function createTokenizer(): Tokenizer {
|
|
6
|
+
return {
|
|
7
|
+
count(text: string): number {
|
|
8
|
+
if (text.length === 0) return 0;
|
|
9
|
+
// ~4 chars per token approximation. Accurate to ±15% for English.
|
|
10
|
+
// Replace with tiktoken for production accuracy.
|
|
11
|
+
return Math.ceil(text.length / 4);
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import type { KernelEvent, TaskState } from "../types";
|
|
2
|
+
|
|
3
|
+
// === AG-UI event shapes (subset we emit in v1) ===
|
|
4
|
+
// These match the AG-UI spec at https://docs.ag-ui.com/concepts/events.md
|
|
5
|
+
|
|
6
|
+
export interface AGUIBaseEvent {
|
|
7
|
+
type: string;
|
|
8
|
+
timestamp?: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface AGUIRunStarted extends AGUIBaseEvent {
|
|
12
|
+
type: "RUN_STARTED";
|
|
13
|
+
threadId: string;
|
|
14
|
+
runId: string;
|
|
15
|
+
parentRunId?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface AGUIRunFinished extends AGUIBaseEvent {
|
|
19
|
+
type: "RUN_FINISHED";
|
|
20
|
+
threadId: string;
|
|
21
|
+
runId: string;
|
|
22
|
+
/**
|
|
23
|
+
* Optional structured result. v1 carries the terminal status discriminator
|
|
24
|
+
* so consumers can distinguish "agent finished" from "agent waiting for
|
|
25
|
+
* user input." Old AG-UI clients that ignore `result` keep working.
|
|
26
|
+
*/
|
|
27
|
+
result?: {
|
|
28
|
+
status: TaskState;
|
|
29
|
+
message?: string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface AGUIRunError extends AGUIBaseEvent {
|
|
34
|
+
type: "RUN_ERROR";
|
|
35
|
+
message: string;
|
|
36
|
+
code?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface AGUITextMessageStart extends AGUIBaseEvent {
|
|
40
|
+
type: "TEXT_MESSAGE_START";
|
|
41
|
+
messageId: string;
|
|
42
|
+
role: "assistant" | "user" | "system" | "tool" | "developer";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface AGUITextMessageContent extends AGUIBaseEvent {
|
|
46
|
+
type: "TEXT_MESSAGE_CONTENT";
|
|
47
|
+
messageId: string;
|
|
48
|
+
delta: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface AGUITextMessageEnd extends AGUIBaseEvent {
|
|
52
|
+
type: "TEXT_MESSAGE_END";
|
|
53
|
+
messageId: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface AGUIToolCallStart extends AGUIBaseEvent {
|
|
57
|
+
type: "TOOL_CALL_START";
|
|
58
|
+
toolCallId: string;
|
|
59
|
+
toolCallName: string;
|
|
60
|
+
parentMessageId?: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface AGUIToolCallArgs extends AGUIBaseEvent {
|
|
64
|
+
type: "TOOL_CALL_ARGS";
|
|
65
|
+
toolCallId: string;
|
|
66
|
+
delta: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface AGUIToolCallEnd extends AGUIBaseEvent {
|
|
70
|
+
type: "TOOL_CALL_END";
|
|
71
|
+
toolCallId: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface AGUIToolCallResult extends AGUIBaseEvent {
|
|
75
|
+
type: "TOOL_CALL_RESULT";
|
|
76
|
+
messageId: string;
|
|
77
|
+
toolCallId: string;
|
|
78
|
+
content: string;
|
|
79
|
+
role?: "tool";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export type AGUIEvent =
|
|
83
|
+
| AGUIRunStarted
|
|
84
|
+
| AGUIRunFinished
|
|
85
|
+
| AGUIRunError
|
|
86
|
+
| AGUITextMessageStart
|
|
87
|
+
| AGUITextMessageContent
|
|
88
|
+
| AGUITextMessageEnd
|
|
89
|
+
| AGUIToolCallStart
|
|
90
|
+
| AGUIToolCallArgs
|
|
91
|
+
| AGUIToolCallEnd
|
|
92
|
+
| AGUIToolCallResult;
|
|
93
|
+
|
|
94
|
+
// === Constructor helpers ===
|
|
95
|
+
|
|
96
|
+
export function runStarted(opts: { threadId: string; runId: string }): AGUIRunStarted {
|
|
97
|
+
return { type: "RUN_STARTED", ...opts };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function runFinished(opts: {
|
|
101
|
+
threadId: string;
|
|
102
|
+
runId: string;
|
|
103
|
+
status?: TaskState;
|
|
104
|
+
message?: string;
|
|
105
|
+
}): AGUIRunFinished {
|
|
106
|
+
const base: AGUIRunFinished = {
|
|
107
|
+
type: "RUN_FINISHED",
|
|
108
|
+
threadId: opts.threadId,
|
|
109
|
+
runId: opts.runId,
|
|
110
|
+
};
|
|
111
|
+
if (opts.status !== undefined) {
|
|
112
|
+
base.result = opts.message
|
|
113
|
+
? { status: opts.status, message: opts.message }
|
|
114
|
+
: { status: opts.status };
|
|
115
|
+
}
|
|
116
|
+
return base;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function runError(opts: { message: string; code?: string }): AGUIRunError {
|
|
120
|
+
return { type: "RUN_ERROR", ...opts };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function textMessageStart(opts: {
|
|
124
|
+
messageId: string;
|
|
125
|
+
role: AGUITextMessageStart["role"];
|
|
126
|
+
}): AGUITextMessageStart {
|
|
127
|
+
return { type: "TEXT_MESSAGE_START", ...opts };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function textMessageContent(opts: {
|
|
131
|
+
messageId: string;
|
|
132
|
+
delta: string;
|
|
133
|
+
}): AGUITextMessageContent {
|
|
134
|
+
return { type: "TEXT_MESSAGE_CONTENT", ...opts };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function textMessageEnd(opts: { messageId: string }): AGUITextMessageEnd {
|
|
138
|
+
return { type: "TEXT_MESSAGE_END", ...opts };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function toolCallStart(opts: {
|
|
142
|
+
toolCallId: string;
|
|
143
|
+
toolCallName: string;
|
|
144
|
+
parentMessageId?: string;
|
|
145
|
+
}): AGUIToolCallStart {
|
|
146
|
+
return { type: "TOOL_CALL_START", ...opts };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function toolCallArgs(opts: { toolCallId: string; delta: string }): AGUIToolCallArgs {
|
|
150
|
+
return { type: "TOOL_CALL_ARGS", ...opts };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function toolCallEnd(opts: { toolCallId: string }): AGUIToolCallEnd {
|
|
154
|
+
return { type: "TOOL_CALL_END", ...opts };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function toolCallResult(opts: {
|
|
158
|
+
messageId: string;
|
|
159
|
+
toolCallId: string;
|
|
160
|
+
content: string;
|
|
161
|
+
}): AGUIToolCallResult {
|
|
162
|
+
return { type: "TOOL_CALL_RESULT", role: "tool", ...opts };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// === Kernel → AG-UI translation ===
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Translate a single kernel event into zero or more AG-UI events.
|
|
169
|
+
* Some kernel events map 1:1, others expand (e.g. text_message emits
|
|
170
|
+
* a START / CONTENT / END triple since v1 doesn't stream tokens).
|
|
171
|
+
*
|
|
172
|
+
* Note: run_finished and run_error emit events with empty threadId —
|
|
173
|
+
* the transport patches it before serialization, since threadId is
|
|
174
|
+
* known at the transport layer.
|
|
175
|
+
*/
|
|
176
|
+
export function translateKernelEvent(event: KernelEvent): AGUIEvent[] {
|
|
177
|
+
switch (event.kind) {
|
|
178
|
+
case "run_started":
|
|
179
|
+
return [runStarted({ threadId: event.threadId, runId: event.turnId })];
|
|
180
|
+
|
|
181
|
+
case "tool_call_started":
|
|
182
|
+
return [
|
|
183
|
+
toolCallStart({
|
|
184
|
+
toolCallId: event.toolCallId,
|
|
185
|
+
toolCallName: event.toolName,
|
|
186
|
+
}),
|
|
187
|
+
];
|
|
188
|
+
|
|
189
|
+
case "tool_call_args":
|
|
190
|
+
return [
|
|
191
|
+
toolCallArgs({
|
|
192
|
+
toolCallId: event.toolCallId,
|
|
193
|
+
delta: JSON.stringify(event.args),
|
|
194
|
+
}),
|
|
195
|
+
];
|
|
196
|
+
|
|
197
|
+
case "tool_call_result":
|
|
198
|
+
return [
|
|
199
|
+
toolCallEnd({ toolCallId: event.toolCallId }),
|
|
200
|
+
toolCallResult({
|
|
201
|
+
messageId: `${event.toolCallId}-result`,
|
|
202
|
+
toolCallId: event.toolCallId,
|
|
203
|
+
content: event.output,
|
|
204
|
+
}),
|
|
205
|
+
];
|
|
206
|
+
|
|
207
|
+
case "text_message":
|
|
208
|
+
return [
|
|
209
|
+
textMessageStart({ messageId: event.messageId, role: event.role }),
|
|
210
|
+
textMessageContent({ messageId: event.messageId, delta: event.text }),
|
|
211
|
+
textMessageEnd({ messageId: event.messageId }),
|
|
212
|
+
];
|
|
213
|
+
|
|
214
|
+
// Streaming text lifecycle: emitted by engines that support onDelta.
|
|
215
|
+
// Each maps 1:1 to its AG-UI counterpart.
|
|
216
|
+
case "text_message_start":
|
|
217
|
+
return [textMessageStart({ messageId: event.messageId, role: event.role })];
|
|
218
|
+
|
|
219
|
+
case "text_message_delta":
|
|
220
|
+
return [textMessageContent({ messageId: event.messageId, delta: event.delta })];
|
|
221
|
+
|
|
222
|
+
case "text_message_end":
|
|
223
|
+
return [textMessageEnd({ messageId: event.messageId })];
|
|
224
|
+
|
|
225
|
+
case "run_finished":
|
|
226
|
+
return [
|
|
227
|
+
runFinished({
|
|
228
|
+
threadId: "",
|
|
229
|
+
runId: event.turnId,
|
|
230
|
+
status: event.status,
|
|
231
|
+
...(event.message !== undefined && { message: event.message }),
|
|
232
|
+
}),
|
|
233
|
+
];
|
|
234
|
+
|
|
235
|
+
case "run_error":
|
|
236
|
+
// Only emit RUN_ERROR here. The turn loop always emits a separate
|
|
237
|
+
// run_finished kernel event after run_error (see turn-loop.ts), which
|
|
238
|
+
// produces the terminal RUN_FINISHED. Emitting one here would cause
|
|
239
|
+
// clients to see two terminal events for a single failing turn.
|
|
240
|
+
return [runError({ message: event.message, code: event.source })];
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// === SSE serialization ===
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Format an AG-UI event as a single Server-Sent Events data frame.
|
|
248
|
+
* Each event is a JSON object prefixed with `data: ` and followed
|
|
249
|
+
* by two newlines to mark the end of the frame.
|
|
250
|
+
*/
|
|
251
|
+
export function serializeSSE(event: AGUIEvent): string {
|
|
252
|
+
return `data: ${JSON.stringify(event)}\n\n`;
|
|
253
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export interface VisitorTokenPayload {
|
|
2
|
+
visitorId: string;
|
|
3
|
+
agentId: string;
|
|
4
|
+
issuedAt: number;
|
|
5
|
+
expiresAt: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const PURPOSE = "auggy-visitor-signing";
|
|
9
|
+
const encoder = new TextEncoder();
|
|
10
|
+
|
|
11
|
+
export async function deriveSigningKey(bearerToken: string): Promise<CryptoKey> {
|
|
12
|
+
const keyMaterial = await crypto.subtle.importKey(
|
|
13
|
+
"raw",
|
|
14
|
+
encoder.encode(bearerToken),
|
|
15
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
16
|
+
false,
|
|
17
|
+
["sign"],
|
|
18
|
+
);
|
|
19
|
+
const derived = await crypto.subtle.sign("HMAC", keyMaterial, encoder.encode(PURPOSE));
|
|
20
|
+
return crypto.subtle.importKey("raw", derived, { name: "HMAC", hash: "SHA-256" }, true, [
|
|
21
|
+
"sign",
|
|
22
|
+
"verify",
|
|
23
|
+
]);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function createVisitorToken(
|
|
27
|
+
key: CryptoKey,
|
|
28
|
+
agentId: string,
|
|
29
|
+
ttlSeconds: number,
|
|
30
|
+
/**
|
|
31
|
+
* Optional pre-existing visitorId. When omitted (the common case for first
|
|
32
|
+
* verification or anonymous-recognized issuance), a fresh `vis_<uuid>` is
|
|
33
|
+
* minted. When provided (re-verification of an already-known email), the
|
|
34
|
+
* existing identifier is preserved so peer-scoped state in layered-memory
|
|
35
|
+
* remains continuous across re-verifications.
|
|
36
|
+
*/
|
|
37
|
+
existingVisitorId?: string,
|
|
38
|
+
): Promise<{ token: string; payload: VisitorTokenPayload }> {
|
|
39
|
+
const payload: VisitorTokenPayload = {
|
|
40
|
+
visitorId: existingVisitorId ?? `vis_${crypto.randomUUID()}`,
|
|
41
|
+
agentId,
|
|
42
|
+
issuedAt: Date.now(),
|
|
43
|
+
expiresAt: Date.now() + ttlSeconds * 1000,
|
|
44
|
+
};
|
|
45
|
+
const payloadB64 = btoa(JSON.stringify(payload));
|
|
46
|
+
const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(payloadB64));
|
|
47
|
+
const sigB64 = btoa(String.fromCharCode(...new Uint8Array(signature)));
|
|
48
|
+
return { token: `${payloadB64}.${sigB64}`, payload };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function verifyVisitorToken(
|
|
52
|
+
key: CryptoKey,
|
|
53
|
+
token: string,
|
|
54
|
+
): Promise<VisitorTokenPayload | null> {
|
|
55
|
+
const parts = token.split(".");
|
|
56
|
+
if (parts.length !== 2) return null;
|
|
57
|
+
const [payloadB64, sigB64] = parts as [string, string];
|
|
58
|
+
|
|
59
|
+
let sigBytes: Uint8Array;
|
|
60
|
+
try {
|
|
61
|
+
sigBytes = Uint8Array.from(atob(sigB64), (c) => c.charCodeAt(0));
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const sigBuffer = sigBytes.buffer.slice(
|
|
67
|
+
sigBytes.byteOffset,
|
|
68
|
+
sigBytes.byteOffset + sigBytes.byteLength,
|
|
69
|
+
) as ArrayBuffer;
|
|
70
|
+
const valid = await crypto.subtle.verify("HMAC", key, sigBuffer, encoder.encode(payloadB64));
|
|
71
|
+
if (!valid) return null;
|
|
72
|
+
|
|
73
|
+
let payload: VisitorTokenPayload;
|
|
74
|
+
try {
|
|
75
|
+
payload = JSON.parse(atob(payloadB64)) as VisitorTokenPayload;
|
|
76
|
+
} catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (payload.expiresAt < Date.now()) return null;
|
|
81
|
+
return payload;
|
|
82
|
+
}
|