agent-sin 0.1.11 → 0.1.15
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 +79 -0
- package/README.md +2 -1
- package/builtin-skills/_shared/_todo_lib.py +290 -0
- package/builtin-skills/even-g2-setup/main.ts +896 -0
- package/builtin-skills/even-g2-setup/skill.yaml +133 -0
- package/builtin-skills/memo-delete/main.py +28 -107
- package/builtin-skills/memo-delete/skill.yaml +10 -21
- package/builtin-skills/memo-index/main.py +96 -64
- package/builtin-skills/memo-index/skill.yaml +4 -10
- package/builtin-skills/memo-list/main.py +179 -0
- package/builtin-skills/memo-list/skill.yaml +51 -0
- package/builtin-skills/memo-save/main.py +191 -25
- package/builtin-skills/memo-save/skill.yaml +29 -5
- package/builtin-skills/memo-search/main.py +38 -18
- package/builtin-skills/memo-vector-search/main.py +11 -6
- package/builtin-skills/nightly-topic-knowledge/_feedback_lib.py +391 -0
- package/builtin-skills/nightly-topic-knowledge/_topics_lib.py +415 -0
- package/builtin-skills/nightly-topic-knowledge/main.py +403 -0
- package/builtin-skills/nightly-topic-knowledge/skill.yaml +88 -0
- package/builtin-skills/schedule-add/main.py +26 -0
- package/builtin-skills/service-restart/main.ts +249 -0
- package/builtin-skills/service-restart/skill.yaml +49 -0
- package/builtin-skills/todo-add/main.py +3 -1
- package/builtin-skills/todo-delete/main.py +3 -1
- package/builtin-skills/todo-done/main.py +3 -1
- package/builtin-skills/todo-list/main.py +4 -1
- package/builtin-skills/todo-tick/main.py +3 -1
- package/builtin-skills/topic-knowledge-read/main.py +118 -0
- package/builtin-skills/topic-knowledge-read/skill.yaml +49 -0
- package/dist/builder/build-action-classifier.d.ts +18 -0
- package/dist/builder/build-action-classifier.js +82 -1
- package/dist/builder/build-flow.d.ts +33 -4
- package/dist/builder/build-flow.js +251 -89
- package/dist/builder/builder-session.d.ts +1 -1
- package/dist/builder/builder-session.js +112 -7
- package/dist/builder/conversation-router.d.ts +4 -2
- package/dist/builder/conversation-router.js +19 -2
- package/dist/cli/index.js +323 -20
- package/dist/core/ai-provider.d.ts +1 -0
- package/dist/core/ai-provider.js +8 -3
- package/dist/core/chat-engine.d.ts +10 -3
- package/dist/core/chat-engine.js +1563 -197
- package/dist/core/config.d.ts +4 -0
- package/dist/core/config.js +82 -0
- package/dist/core/daily-memory-promotion.d.ts +7 -0
- package/dist/core/daily-memory-promotion.js +568 -14
- package/dist/core/image-attachments.d.ts +31 -0
- package/dist/core/image-attachments.js +237 -0
- package/dist/core/logger.d.ts +2 -1
- package/dist/core/logger.js +77 -1
- package/dist/core/memo-migration.d.ts +3 -0
- package/dist/core/memo-migration.js +422 -0
- package/dist/core/native-modules.d.ts +24 -0
- package/dist/core/native-modules.js +99 -0
- package/dist/core/notifier.d.ts +8 -3
- package/dist/core/notifier.js +191 -17
- package/dist/core/obsidian-vault.d.ts +19 -0
- package/dist/core/obsidian-vault.js +477 -0
- package/dist/core/operating-model.d.ts +2 -0
- package/dist/core/operating-model.js +15 -0
- package/dist/core/output-writer.d.ts +3 -2
- package/dist/core/output-writer.js +108 -7
- package/dist/core/profile-memory.js +22 -1
- package/dist/core/runtime.d.ts +2 -0
- package/dist/core/runtime.js +9 -1
- package/dist/core/secrets.d.ts +4 -0
- package/dist/core/secrets.js +34 -0
- package/dist/core/skill-history.d.ts +44 -0
- package/dist/core/skill-history.js +329 -0
- package/dist/core/skill-registry.d.ts +5 -0
- package/dist/core/skill-registry.js +11 -0
- package/dist/discord/bot.d.ts +13 -0
- package/dist/discord/bot.js +542 -10
- package/dist/even-g2/gateway.d.ts +15 -0
- package/dist/even-g2/gateway.js +868 -0
- package/dist/runtimes/codex-app-server.d.ts +5 -1
- package/dist/runtimes/codex-app-server.js +147 -8
- package/dist/runtimes/python-runner.js +82 -0
- package/dist/runtimes/typescript-runner.js +13 -1
- package/dist/skills-sdk/types.d.ts +19 -4
- package/dist/telegram/bot.d.ts +1 -0
- package/dist/telegram/bot.js +122 -31
- package/package.json +3 -1
- package/templates/even-g2-agent/README.md +83 -0
- package/templates/even-g2-agent/app.json +20 -0
- package/templates/even-g2-agent/index.html +31 -0
- package/templates/even-g2-agent/package-lock.json +1836 -0
- package/templates/even-g2-agent/package.json +22 -0
- package/templates/even-g2-agent/scripts/qr-auto.mjs +182 -0
- package/templates/even-g2-agent/src/embedded-config.ts +4 -0
- package/templates/even-g2-agent/src/main.ts +539 -0
- package/templates/even-g2-agent/src/style.css +70 -0
- package/templates/even-g2-agent/tsconfig.json +11 -0
- package/templates/skill-python/main.py +20 -2
- package/templates/skill-python/skill.yaml +9 -0
- package/templates/skill-typescript/main.ts +40 -5
- package/templates/skill-typescript/skill.yaml +9 -0
|
@@ -30,6 +30,10 @@ export interface CodexAppServerOptions {
|
|
|
30
30
|
turnTimeoutMs?: number;
|
|
31
31
|
onStderr?: (chunk: string) => void;
|
|
32
32
|
}
|
|
33
|
+
export interface CodexTurnResult {
|
|
34
|
+
text: string;
|
|
35
|
+
generatedImagePaths: string[];
|
|
36
|
+
}
|
|
33
37
|
export declare function getSharedCodexAppServer(model?: string): CodexAppServerSession;
|
|
34
38
|
export declare function shutdownSharedCodexAppServer(): Promise<void>;
|
|
35
39
|
export declare class CodexAppServerSession {
|
|
@@ -42,7 +46,7 @@ export declare class CodexAppServerSession {
|
|
|
42
46
|
private readonly options;
|
|
43
47
|
private exitReason;
|
|
44
48
|
constructor(options?: CodexAppServerOptions);
|
|
45
|
-
sendTurn(text: string, options?: CodexTurnOptions): Promise<
|
|
49
|
+
sendTurn(text: string, options?: CodexTurnOptions): Promise<CodexTurnResult>;
|
|
46
50
|
stop(): Promise<void>;
|
|
47
51
|
isRunning(): boolean;
|
|
48
52
|
private ensureStarted;
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
+
import crypto from "node:crypto";
|
|
3
|
+
import { mkdir, stat, writeFile } from "node:fs/promises";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { detectImageMimeTypeFromBuffer, imageExtensionForMimeType, } from "../core/image-attachments.js";
|
|
2
7
|
import { l } from "../core/i18n.js";
|
|
3
8
|
const DEFAULT_STARTUP_TIMEOUT_MS = 30_000;
|
|
4
9
|
const DEFAULT_TURN_TIMEOUT_MS = 5 * 60_000;
|
|
10
|
+
const MAX_GENERATED_IMAGE_BYTES = 20 * 1024 * 1024;
|
|
5
11
|
function snippet(value) {
|
|
6
12
|
if (typeof value !== "string") {
|
|
7
13
|
return undefined;
|
|
@@ -40,8 +46,8 @@ export class CodexAppServerSession {
|
|
|
40
46
|
constructor(options = {}) {
|
|
41
47
|
const baseArgs = options.args ? [...options.args] : ["app-server"];
|
|
42
48
|
const model = options.model || process.env.AGENT_SIN_CODEX_MODEL;
|
|
43
|
-
if (model && !baseArgs
|
|
44
|
-
baseArgs.push("
|
|
49
|
+
if (model && !hasConfigOverride(baseArgs, "model")) {
|
|
50
|
+
baseArgs.push("-c", `model=${JSON.stringify(model)}`);
|
|
45
51
|
}
|
|
46
52
|
this.options = {
|
|
47
53
|
bin: options.bin || process.env.AGENT_SIN_CODEX_BIN || "codex",
|
|
@@ -211,6 +217,9 @@ export class CodexAppServerSession {
|
|
|
211
217
|
return new Promise((resolve, reject) => {
|
|
212
218
|
let assistantText = "";
|
|
213
219
|
let settled = false;
|
|
220
|
+
const generatedImagePaths = [];
|
|
221
|
+
const generatedImageKeys = new Set();
|
|
222
|
+
const generatedImageTasks = [];
|
|
214
223
|
const emit = (event) => {
|
|
215
224
|
if (!options.onProgress) {
|
|
216
225
|
return;
|
|
@@ -259,6 +268,17 @@ export class CodexAppServerSession {
|
|
|
259
268
|
else if (item && (item.type === "command" || item.type === "tool_call")) {
|
|
260
269
|
emit({ kind: "tool", name: item.name || item.type, text: l("done", "完了") });
|
|
261
270
|
}
|
|
271
|
+
else if (item && item.type === "imageGeneration") {
|
|
272
|
+
generatedImageTasks.push(captureGeneratedImage(item, options.cwd, generatedImagePaths, generatedImageKeys));
|
|
273
|
+
emit({ kind: "tool", name: "image_generation", text: l("done", "完了") });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
else if (method === "rawResponseItem/completed") {
|
|
277
|
+
const item = params.item;
|
|
278
|
+
if (item && item.type === "image_generation_call") {
|
|
279
|
+
generatedImageTasks.push(captureGeneratedImage(item, options.cwd, generatedImagePaths, generatedImageKeys));
|
|
280
|
+
emit({ kind: "tool", name: "image_generation", text: l("done", "完了") });
|
|
281
|
+
}
|
|
262
282
|
}
|
|
263
283
|
else if (method === "turn/completed") {
|
|
264
284
|
const turn = params.turn;
|
|
@@ -270,6 +290,11 @@ export class CodexAppServerSession {
|
|
|
270
290
|
if (fromTurn) {
|
|
271
291
|
assistantText = fromTurn;
|
|
272
292
|
}
|
|
293
|
+
for (const entry of turn.items) {
|
|
294
|
+
if (entry && entry.type === "imageGeneration") {
|
|
295
|
+
generatedImageTasks.push(captureGeneratedImage(entry, options.cwd, generatedImagePaths, generatedImageKeys));
|
|
296
|
+
}
|
|
297
|
+
}
|
|
273
298
|
}
|
|
274
299
|
finish(true, undefined);
|
|
275
300
|
}
|
|
@@ -285,12 +310,23 @@ export class CodexAppServerSession {
|
|
|
285
310
|
settled = true;
|
|
286
311
|
clearTimeout(timeout);
|
|
287
312
|
this.notificationHandlers.delete(handler);
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
313
|
+
Promise.all(generatedImageTasks)
|
|
314
|
+
.then(() => {
|
|
315
|
+
if (ok) {
|
|
316
|
+
resolve({ text: assistantText, generatedImagePaths });
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
reject(error || new Error("codex app-server: unknown failure"));
|
|
320
|
+
}
|
|
321
|
+
})
|
|
322
|
+
.catch((imageError) => {
|
|
323
|
+
if (ok) {
|
|
324
|
+
resolve({ text: assistantText, generatedImagePaths });
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
reject(error || imageError);
|
|
328
|
+
}
|
|
329
|
+
});
|
|
294
330
|
};
|
|
295
331
|
const timeout = setTimeout(() => {
|
|
296
332
|
finish(false, new Error(`codex app-server: turn timed out after ${this.options.turnTimeoutMs}ms`));
|
|
@@ -306,3 +342,106 @@ export class CodexAppServerSession {
|
|
|
306
342
|
});
|
|
307
343
|
}
|
|
308
344
|
}
|
|
345
|
+
function hasConfigOverride(args, key) {
|
|
346
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
347
|
+
const arg = args[index];
|
|
348
|
+
if ((arg === "-c" || arg === "--config") && args[index + 1]?.startsWith(`${key}=`)) {
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
if (arg.startsWith("-c") && arg.slice(2).trimStart().startsWith(`${key}=`)) {
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
if (arg.startsWith("--config=") && arg.slice("--config=".length).startsWith(`${key}=`)) {
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
async function captureGeneratedImage(item, cwd, paths, keys) {
|
|
361
|
+
if (!item || typeof item !== "object")
|
|
362
|
+
return;
|
|
363
|
+
const record = item;
|
|
364
|
+
const id = typeof record.id === "string" ? record.id : undefined;
|
|
365
|
+
const savedPath = typeof record.savedPath === "string" ? record.savedPath : undefined;
|
|
366
|
+
const result = typeof record.result === "string" ? record.result : undefined;
|
|
367
|
+
const key = id || (result ? imageResultKey(result) : savedPath);
|
|
368
|
+
if (key && keys.has(key))
|
|
369
|
+
return;
|
|
370
|
+
if (key)
|
|
371
|
+
keys.add(key);
|
|
372
|
+
if (savedPath) {
|
|
373
|
+
const usable = await existingImagePath(savedPath);
|
|
374
|
+
if (usable && !paths.includes(usable)) {
|
|
375
|
+
paths.push(usable);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
if (!result)
|
|
380
|
+
return;
|
|
381
|
+
const resultPath = await persistImageGenerationResult(result, cwd, id);
|
|
382
|
+
if (resultPath && !paths.includes(resultPath)) {
|
|
383
|
+
paths.push(resultPath);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
async function existingImagePath(filePath) {
|
|
387
|
+
try {
|
|
388
|
+
const info = await stat(filePath);
|
|
389
|
+
return info.isFile() && info.size > 0 ? filePath : null;
|
|
390
|
+
}
|
|
391
|
+
catch {
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
async function persistImageGenerationResult(value, cwd, id) {
|
|
396
|
+
const parsed = parseImageGenerationResult(value);
|
|
397
|
+
if (!parsed || parsed.buffer.length === 0 || parsed.buffer.length > MAX_GENERATED_IMAGE_BYTES) {
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
const mimeType = parsed.mimeType || detectImageMimeTypeFromBuffer(parsed.buffer);
|
|
401
|
+
const ext = imageExtensionForMimeType(mimeType);
|
|
402
|
+
const safeId = (id || "image").replace(/[^a-zA-Z0-9_-]/g, "").slice(0, 40) || "image";
|
|
403
|
+
const hash = crypto.createHash("sha256").update(parsed.buffer).digest("hex").slice(0, 10);
|
|
404
|
+
const filename = `${new Date().toISOString().replace(/[:.]/g, "-")}-${safeId}-${hash}${ext}`;
|
|
405
|
+
for (const dir of candidateImageDirs(cwd)) {
|
|
406
|
+
try {
|
|
407
|
+
await mkdir(dir, { recursive: true });
|
|
408
|
+
const filePath = path.join(dir, filename);
|
|
409
|
+
await writeFile(filePath, parsed.buffer);
|
|
410
|
+
return filePath;
|
|
411
|
+
}
|
|
412
|
+
catch {
|
|
413
|
+
// Try the fallback directory.
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
418
|
+
function parseImageGenerationResult(value) {
|
|
419
|
+
const trimmed = value.trim();
|
|
420
|
+
const dataUrl = trimmed.match(/^data:(image\/[a-z0-9.+-]+);base64,([\s\S]+)$/i);
|
|
421
|
+
const mimeType = dataUrl?.[1];
|
|
422
|
+
const rawBase64 = dataUrl ? dataUrl[2] : trimmed;
|
|
423
|
+
if (rawBase64.length === 0 || rawBase64.length > Math.ceil(MAX_GENERATED_IMAGE_BYTES * 1.4)) {
|
|
424
|
+
return null;
|
|
425
|
+
}
|
|
426
|
+
if (!/^[A-Za-z0-9+/=\s_-]+$/.test(rawBase64)) {
|
|
427
|
+
return null;
|
|
428
|
+
}
|
|
429
|
+
const normalized = rawBase64.replace(/[\s_-]/g, (char) => (char === "-" ? "+" : char === "_" ? "/" : ""));
|
|
430
|
+
try {
|
|
431
|
+
return { buffer: Buffer.from(normalized, "base64"), mimeType };
|
|
432
|
+
}
|
|
433
|
+
catch {
|
|
434
|
+
return null;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
function candidateImageDirs(cwd) {
|
|
438
|
+
const dirs = [];
|
|
439
|
+
if (cwd) {
|
|
440
|
+
dirs.push(path.join(cwd, "codex-images"));
|
|
441
|
+
}
|
|
442
|
+
dirs.push(path.join(os.tmpdir(), "agent-sin-codex-images"));
|
|
443
|
+
return dirs;
|
|
444
|
+
}
|
|
445
|
+
function imageResultKey(value) {
|
|
446
|
+
return crypto.createHash("sha256").update(value).digest("hex");
|
|
447
|
+
}
|
|
@@ -4,10 +4,13 @@ import path from "node:path";
|
|
|
4
4
|
import { resolveSkillEntryPath } from "../core/skill-registry.js";
|
|
5
5
|
import { getAiProvider } from "../core/ai-provider.js";
|
|
6
6
|
import { notify as runNotify } from "../core/notifier.js";
|
|
7
|
+
import { appendSkillHistory, listSkillHistory, readSkillHistoryRaw, } from "../core/skill-history.js";
|
|
7
8
|
const AI_REQUEST_PREFIX = "AGENT_SIN_AI_REQUEST::";
|
|
8
9
|
const AI_RESPONSE_PREFIX = "AGENT_SIN_AI_RESPONSE::";
|
|
9
10
|
const NOTIFY_REQUEST_PREFIX = "AGENT_SIN_NOTIFY_REQUEST::";
|
|
10
11
|
const NOTIFY_RESPONSE_PREFIX = "AGENT_SIN_NOTIFY_RESPONSE::";
|
|
12
|
+
const HISTORY_REQUEST_PREFIX = "AGENT_SIN_HISTORY_REQUEST::";
|
|
13
|
+
const HISTORY_RESPONSE_PREFIX = "AGENT_SIN_HISTORY_RESPONSE::";
|
|
11
14
|
const CTX_LOG_PATTERN = /^\[(info|warn|error)\]\s+([\s\S]*)$/;
|
|
12
15
|
export function candidatePythonInterpreters(config, platform = process.platform) {
|
|
13
16
|
const venvDir = path.join(config.workspace, ".venv");
|
|
@@ -83,6 +86,13 @@ export async function runPythonSkill(config, manifest, input) {
|
|
|
83
86
|
});
|
|
84
87
|
return;
|
|
85
88
|
}
|
|
89
|
+
if (line.startsWith(HISTORY_REQUEST_PREFIX)) {
|
|
90
|
+
const payloadJson = line.slice(HISTORY_REQUEST_PREFIX.length);
|
|
91
|
+
handleHistoryRequest(payloadJson).catch((error) => {
|
|
92
|
+
stderrLines.push(`[history-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
93
|
+
});
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
86
96
|
const ctxMatch = line.match(CTX_LOG_PATTERN);
|
|
87
97
|
if (ctxMatch) {
|
|
88
98
|
ctxLogs.push({ level: ctxMatch[1], message: ctxMatch[2] });
|
|
@@ -103,6 +113,7 @@ export async function runPythonSkill(config, manifest, input) {
|
|
|
103
113
|
const response = await getAiProvider()(config, {
|
|
104
114
|
model_id: request.model_id,
|
|
105
115
|
messages: request.messages,
|
|
116
|
+
cwd: config.workspace,
|
|
106
117
|
});
|
|
107
118
|
child.stdin.write(`${AI_RESPONSE_PREFIX}${JSON.stringify({ id: request.id, ok: true, response })}\n`);
|
|
108
119
|
}
|
|
@@ -114,6 +125,40 @@ export async function runPythonSkill(config, manifest, input) {
|
|
|
114
125
|
})}\n`);
|
|
115
126
|
}
|
|
116
127
|
}
|
|
128
|
+
async function handleHistoryRequest(payloadJson) {
|
|
129
|
+
let request;
|
|
130
|
+
try {
|
|
131
|
+
request = JSON.parse(payloadJson);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
child.stdin.write(`${HISTORY_RESPONSE_PREFIX}${JSON.stringify({ id: "?", ok: false, error: `Invalid history request JSON: ${String(error)}` })}\n`);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
const payload = request.payload || {};
|
|
139
|
+
let data = null;
|
|
140
|
+
if (request.op === "append") {
|
|
141
|
+
data = await appendSkillHistory(config, manifest, payload);
|
|
142
|
+
}
|
|
143
|
+
else if (request.op === "list") {
|
|
144
|
+
data = await listSkillHistory(config, manifest, payload);
|
|
145
|
+
}
|
|
146
|
+
else if (request.op === "read") {
|
|
147
|
+
data = await readSkillHistoryRaw(config, manifest, payload);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
throw new Error(`Unknown history op: ${request.op}`);
|
|
151
|
+
}
|
|
152
|
+
child.stdin.write(`${HISTORY_RESPONSE_PREFIX}${JSON.stringify({ id: request.id, ok: true, data })}\n`);
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
child.stdin.write(`${HISTORY_RESPONSE_PREFIX}${JSON.stringify({
|
|
156
|
+
id: request.id,
|
|
157
|
+
ok: false,
|
|
158
|
+
error: error instanceof Error ? error.message : String(error),
|
|
159
|
+
})}\n`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
117
162
|
async function handleNotifyRequest(payloadJson) {
|
|
118
163
|
let request;
|
|
119
164
|
try {
|
|
@@ -134,6 +179,15 @@ export async function runPythonSkill(config, manifest, input) {
|
|
|
134
179
|
to: typeof args.to === "string" ? args.to : undefined,
|
|
135
180
|
discordThreadId: typeof args.discordThreadId === "string" ? args.discordThreadId : undefined,
|
|
136
181
|
telegramThreadId: typeof args.telegramThreadId === "string" ? args.telegramThreadId : undefined,
|
|
182
|
+
filePath: typeof args.filePath === "string" ? args.filePath : undefined,
|
|
183
|
+
filePaths: Array.isArray(args.filePaths)
|
|
184
|
+
? args.filePaths.filter((item) => typeof item === "string")
|
|
185
|
+
: undefined,
|
|
186
|
+
imagePath: typeof args.imagePath === "string" ? args.imagePath : undefined,
|
|
187
|
+
imagePaths: Array.isArray(args.imagePaths)
|
|
188
|
+
? args.imagePaths.filter((item) => typeof item === "string")
|
|
189
|
+
: undefined,
|
|
190
|
+
cwd: config.workspace,
|
|
137
191
|
});
|
|
138
192
|
child.stdin.write(`${NOTIFY_RESPONSE_PREFIX}${JSON.stringify({ id: request.id, ok: result.ok, channel: result.channel, detail: result.detail })}\n`);
|
|
139
193
|
}
|
|
@@ -238,6 +292,7 @@ class AI:
|
|
|
238
292
|
"model_id": response.get("model_id"),
|
|
239
293
|
"provider": response.get("provider"),
|
|
240
294
|
"text": response.get("text", ""),
|
|
295
|
+
"generated_images": response.get("generated_images") or [],
|
|
241
296
|
}
|
|
242
297
|
|
|
243
298
|
class Memory:
|
|
@@ -275,11 +330,38 @@ async def notify_call(args):
|
|
|
275
330
|
"detail": envelope.get("detail"),
|
|
276
331
|
}
|
|
277
332
|
|
|
333
|
+
async def history_call(op, payload):
|
|
334
|
+
request_id = str(uuid.uuid4())
|
|
335
|
+
request = {"id": request_id, "op": op, "payload": payload or {}}
|
|
336
|
+
print("AGENT_SIN_HISTORY_REQUEST::" + json.dumps(request, ensure_ascii=False, default=str), file=sys.stderr, flush=True)
|
|
337
|
+
line = sys.stdin.readline()
|
|
338
|
+
if not line:
|
|
339
|
+
raise RuntimeError("History channel closed")
|
|
340
|
+
marker = "AGENT_SIN_HISTORY_RESPONSE::"
|
|
341
|
+
idx = line.find(marker)
|
|
342
|
+
if idx < 0:
|
|
343
|
+
raise RuntimeError(f"Unexpected history response: {line.strip()}")
|
|
344
|
+
envelope = json.loads(line[idx + len(marker):])
|
|
345
|
+
if not envelope.get("ok"):
|
|
346
|
+
raise RuntimeError(envelope.get("error") or "History error")
|
|
347
|
+
return envelope.get("data")
|
|
348
|
+
|
|
349
|
+
class History:
|
|
350
|
+
async def append(self, args):
|
|
351
|
+
if not isinstance(args, dict):
|
|
352
|
+
raise RuntimeError("ctx.history.append requires a dict argument")
|
|
353
|
+
return await history_call("append", args)
|
|
354
|
+
async def list(self, options=None):
|
|
355
|
+
return await history_call("list", options or {})
|
|
356
|
+
async def read(self, options=None):
|
|
357
|
+
return await history_call("read", options or {})
|
|
358
|
+
|
|
278
359
|
class Ctx:
|
|
279
360
|
def __init__(self):
|
|
280
361
|
self.log = Log()
|
|
281
362
|
self.ai = AI()
|
|
282
363
|
self.memory = Memory()
|
|
364
|
+
self.history = History()
|
|
283
365
|
def now(self):
|
|
284
366
|
return datetime.now(timezone.utc).isoformat()
|
|
285
367
|
async def notify(self, args):
|
|
@@ -7,6 +7,7 @@ import ts from "typescript";
|
|
|
7
7
|
import { resolveSkillEntryPath } from "../core/skill-registry.js";
|
|
8
8
|
import { getAiProvider } from "../core/ai-provider.js";
|
|
9
9
|
import { notify as runNotify } from "../core/notifier.js";
|
|
10
|
+
import { appendSkillHistory, listSkillHistory, readSkillHistoryRaw, } from "../core/skill-history.js";
|
|
10
11
|
export async function runTypeScriptSkill(config, manifest, input) {
|
|
11
12
|
const entry = await resolveSkillEntryPath(manifest);
|
|
12
13
|
const skillDir = await realpath(manifest.dir);
|
|
@@ -113,13 +114,14 @@ function createContext(config, manifest, initialMemory) {
|
|
|
113
114
|
{ role: "system", content: `You are an AI step "${step.id}" of an Agent-Sin skill. Purpose: ${step.purpose}` },
|
|
114
115
|
{ role: "user", content: typeof payload === "string" ? payload : JSON.stringify(payload) },
|
|
115
116
|
];
|
|
116
|
-
const response = await getAiProvider()(config, { model_id: modelId, messages });
|
|
117
|
+
const response = await getAiProvider()(config, { model_id: modelId, messages, cwd: config.workspace });
|
|
117
118
|
return {
|
|
118
119
|
status: "ok",
|
|
119
120
|
step_id: stepId,
|
|
120
121
|
model_id: modelId,
|
|
121
122
|
provider: response.provider,
|
|
122
123
|
text: response.text,
|
|
124
|
+
generated_images: response.generated_images || [],
|
|
123
125
|
};
|
|
124
126
|
}
|
|
125
127
|
catch (error) {
|
|
@@ -145,6 +147,11 @@ function createContext(config, manifest, initialMemory) {
|
|
|
145
147
|
to: args.to,
|
|
146
148
|
discordThreadId: args.discordThreadId,
|
|
147
149
|
telegramThreadId: args.telegramThreadId,
|
|
150
|
+
filePath: args.filePath,
|
|
151
|
+
filePaths: args.filePaths,
|
|
152
|
+
imagePath: args.imagePath,
|
|
153
|
+
imagePaths: args.imagePaths,
|
|
154
|
+
cwd: config.workspace,
|
|
148
155
|
});
|
|
149
156
|
return { ok: result.ok, channel: result.channel, detail: result.detail };
|
|
150
157
|
},
|
|
@@ -164,6 +171,11 @@ function createContext(config, manifest, initialMemory) {
|
|
|
164
171
|
return true;
|
|
165
172
|
},
|
|
166
173
|
},
|
|
174
|
+
history: {
|
|
175
|
+
append: async (args) => appendSkillHistory(config, manifest, args),
|
|
176
|
+
list: async (options = {}) => listSkillHistory(config, manifest, options),
|
|
177
|
+
read: async (options = {}) => readSkillHistoryRaw(config, manifest, options),
|
|
178
|
+
},
|
|
167
179
|
now: () => new Date().toISOString(),
|
|
168
180
|
},
|
|
169
181
|
memoryUpdates,
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
export interface SkillInputSources {
|
|
2
|
+
workspace?: string;
|
|
3
|
+
notes_dir?: string;
|
|
4
|
+
memory_dir?: string;
|
|
5
|
+
index_dir?: string;
|
|
6
|
+
logs_dir?: string;
|
|
7
|
+
skill_output_dir?: string;
|
|
8
|
+
skillOutputDir?: string;
|
|
9
|
+
locale?: string;
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
1
12
|
export interface SkillInput {
|
|
2
13
|
args: Record<string, unknown>;
|
|
3
14
|
trigger: {
|
|
@@ -5,19 +16,23 @@ export interface SkillInput {
|
|
|
5
16
|
id: string;
|
|
6
17
|
time: string;
|
|
7
18
|
};
|
|
8
|
-
sources:
|
|
19
|
+
sources: SkillInputSources;
|
|
9
20
|
memory: Record<string, unknown>;
|
|
10
21
|
}
|
|
11
|
-
export type NotifyChannel = "auto" | "macos" | "discord" | "telegram" | "slack" | "mail" | "stderr";
|
|
22
|
+
export type NotifyChannel = "auto" | "macos" | "discord" | "telegram" | "slack" | "mail" | "g2" | "stderr";
|
|
12
23
|
export interface NotifyArgs {
|
|
13
|
-
title
|
|
14
|
-
body
|
|
24
|
+
title?: string;
|
|
25
|
+
body?: string;
|
|
15
26
|
subtitle?: string;
|
|
16
27
|
sound?: boolean;
|
|
17
28
|
channel?: NotifyChannel;
|
|
18
29
|
to?: string;
|
|
19
30
|
discordThreadId?: string;
|
|
20
31
|
telegramThreadId?: string;
|
|
32
|
+
filePath?: string;
|
|
33
|
+
filePaths?: string[];
|
|
34
|
+
imagePath?: string;
|
|
35
|
+
imagePaths?: string[];
|
|
21
36
|
}
|
|
22
37
|
export interface NotifyOutcome {
|
|
23
38
|
ok: boolean;
|
package/dist/telegram/bot.d.ts
CHANGED
|
@@ -90,5 +90,6 @@ export declare function shouldUseTelegramDraftStream(message: TelegramMessage):
|
|
|
90
90
|
export declare function telegramSendPayload(chatId: string, content: string, options?: TelegramSendOptions): Record<string, unknown>;
|
|
91
91
|
export declare function telegramDraftPayload(message: TelegramMessage, draftId: number, text: string): Record<string, unknown>;
|
|
92
92
|
export declare function formatTelegramDraftProgress(event: AiProgressEvent): string | null;
|
|
93
|
+
export declare function formatTelegramChatDraftProgress(event: AiProgressEvent): string | null;
|
|
93
94
|
export declare function loadTelegramHistories(filePath: string): Promise<Map<string, ChatTurn[]>>;
|
|
94
95
|
export declare function loadTelegramIntentRuntimes(filePath: string): Promise<Map<string, IntentRuntime>>;
|