@dream-craft/canvas-agent 0.0.0-stage → 0.6.4

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.
Files changed (49) hide show
  1. package/README.md +165 -3
  2. package/agent-instructions.md +20 -0
  3. package/dist/agent/claude.d.ts +3 -0
  4. package/dist/agent/claude.js +54 -0
  5. package/dist/agent/codex-client.d.ts +139 -0
  6. package/dist/agent/codex-client.js +937 -0
  7. package/dist/agent/codex-event-history.d.ts +21 -0
  8. package/dist/agent/codex-event-history.js +163 -0
  9. package/dist/agent/codex-history.d.ts +46 -0
  10. package/dist/agent/codex-history.js +831 -0
  11. package/dist/agent/codex-protocol.d.ts +335 -0
  12. package/dist/agent/codex-protocol.js +1 -0
  13. package/dist/agent/codex.d.ts +178 -0
  14. package/dist/agent/codex.js +514 -0
  15. package/dist/agent/message-metadata.d.ts +51 -0
  16. package/dist/agent/message-metadata.js +378 -0
  17. package/dist/agent/types.d.ts +45 -0
  18. package/dist/agent/types.js +1 -0
  19. package/dist/canvas/operations.d.ts +13 -0
  20. package/dist/canvas/operations.js +167 -0
  21. package/dist/canvas/schemas.d.ts +1040 -0
  22. package/dist/canvas/schemas.js +193 -0
  23. package/dist/canvas/session.d.ts +163 -0
  24. package/dist/canvas/session.js +528 -0
  25. package/dist/canvas/tools.d.ts +222 -0
  26. package/dist/canvas/tools.js +27 -0
  27. package/dist/canvas/types.d.ts +34 -0
  28. package/dist/canvas/types.js +1 -0
  29. package/dist/config.d.ts +30 -0
  30. package/dist/config.js +86 -0
  31. package/dist/index.d.ts +2 -0
  32. package/dist/index.js +7 -0
  33. package/dist/server/http.d.ts +2 -0
  34. package/dist/server/http.js +607 -0
  35. package/dist/server/mcp.d.ts +2 -0
  36. package/dist/server/mcp.js +60 -0
  37. package/dist/skills/store.d.ts +54 -0
  38. package/dist/skills/store.js +426 -0
  39. package/dist/utils/agent-runtime.d.ts +8 -0
  40. package/dist/utils/agent-runtime.js +33 -0
  41. package/dist/utils/date.d.ts +2 -0
  42. package/dist/utils/date.js +7 -0
  43. package/dist/utils/logger.d.ts +17 -0
  44. package/dist/utils/logger.js +81 -0
  45. package/dist/utils/value.d.ts +5 -0
  46. package/dist/utils/value.js +8 -0
  47. package/dist/version-check.d.ts +2 -0
  48. package/dist/version-check.js +65 -0
  49. package/package.json +46 -6
@@ -0,0 +1,81 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { inspect } from "node:util";
5
+ import winston, { format, transports } from "winston";
6
+ import { formatDateForFilename } from "./date.js";
7
+ /** 管理 Canvas Agent 的终端与文件 Debug 日志。 */
8
+ export class Logger {
9
+ enabled = process.argv.includes("--debug");
10
+ filePath = this.enabled ? path.join(os.homedir(), ".infinite-canvas", "logs", `canvas-agent-${formatDateForFilename()}.log`) : "";
11
+ logger;
12
+ /** 普通模式输出 Info 以上日志,Debug 模式额外输出 Debug 并写入文件。 */
13
+ constructor() {
14
+ const line = format.printf(({ level, message, timestamp, details }) => `${timestamp} ${level.toUpperCase()} ${message}${formatDetails(details)}`);
15
+ const output = format.combine(format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), line);
16
+ if (this.enabled)
17
+ fs.mkdirSync(path.dirname(this.filePath), { recursive: true });
18
+ this.logger = winston.createLogger({
19
+ level: this.enabled ? "debug" : "info",
20
+ transports: [
21
+ new transports.Console({ format: output }),
22
+ ...(this.enabled ? [new transports.File({ filename: this.filePath, format: output })] : []),
23
+ ],
24
+ });
25
+ }
26
+ /** 输出 Debug 级别日志。 */
27
+ debug(message, details) {
28
+ if (details === undefined)
29
+ this.logger.debug(message);
30
+ else
31
+ this.logger.debug(message, { details: sanitize(details) });
32
+ }
33
+ /** 输出 Info 级别日志。 */
34
+ info(message, details) {
35
+ if (details === undefined)
36
+ this.logger.info(message);
37
+ else
38
+ this.logger.info(message, { details: sanitize(details) });
39
+ }
40
+ /** 输出 Warn 级别日志。 */
41
+ warn(message, details) {
42
+ if (details === undefined)
43
+ this.logger.warn(message);
44
+ else
45
+ this.logger.warn(message, { details: sanitize(details) });
46
+ }
47
+ /** 输出 Error 级别日志。 */
48
+ error(message, details) {
49
+ if (details === undefined)
50
+ this.logger.error(message);
51
+ else
52
+ this.logger.error(message, { details: sanitize(details) });
53
+ }
54
+ }
55
+ /** 将日志详情格式化为紧凑的单行文本。 */
56
+ function formatDetails(details) {
57
+ if (details === undefined)
58
+ return "";
59
+ if (!details || typeof details !== "object" || Array.isArray(details))
60
+ return ` ${inspect(details, { depth: null, breakLength: Infinity })}`;
61
+ const text = Object.entries(details).filter(([, value]) => value !== undefined).map(([key, value]) => `${key}=${inspect(value, { depth: null, breakLength: Infinity })}`).join(" ");
62
+ return text ? ` ${text}` : "";
63
+ }
64
+ /** 清理日志内容中的敏感数据和不可序列化引用。 */
65
+ function sanitize(value, key = "", seen = new WeakSet()) {
66
+ if (/token|authorization|api.?key|dataurl/i.test(key))
67
+ return "[REDACTED]";
68
+ if (typeof value === "string" && value.startsWith("data:"))
69
+ return `[DATA URL ${value.length} chars]`;
70
+ if (value instanceof Error)
71
+ return { name: value.name, message: value.message, stack: value.stack };
72
+ if (!value || typeof value !== "object")
73
+ return value;
74
+ if (seen.has(value))
75
+ return "[CIRCULAR]";
76
+ seen.add(value);
77
+ if (Array.isArray(value))
78
+ return value.map((item) => sanitize(item, key, seen));
79
+ return Object.fromEntries(Object.entries(value).map(([field, item]) => [field, sanitize(item, field, seen)]));
80
+ }
81
+ export const logger = new Logger();
@@ -0,0 +1,5 @@
1
+ export type JsonRecord = Record<string, unknown>;
2
+ /** 安全读取未知对象中的指定字段。 */
3
+ export declare function field(value: unknown, key: string): unknown;
4
+ /** 将未知异常转换为可展示的错误信息。 */
5
+ export declare function errorMessage(error: unknown): string;
@@ -0,0 +1,8 @@
1
+ /** 安全读取未知对象中的指定字段。 */
2
+ export function field(value, key) {
3
+ return value && typeof value === "object" ? value[key] : undefined;
4
+ }
5
+ /** 将未知异常转换为可展示的错误信息。 */
6
+ export function errorMessage(error) {
7
+ return error instanceof Error ? error.message : String(error);
8
+ }
@@ -0,0 +1,2 @@
1
+ /** 输出当前版本,并在后台检查 npm 最新版本。 */
2
+ export declare function checkVersions(): void;
@@ -0,0 +1,65 @@
1
+ import { execFile, execFileSync } from "node:child_process";
2
+ import { createRequire } from "node:module";
3
+ import { promisify } from "node:util";
4
+ import { VERSION } from "./config.js";
5
+ import { logger } from "./utils/logger.js";
6
+ const require = createRequire(import.meta.url);
7
+ const execFileAsync = promisify(execFile);
8
+ const CODEX_VERSION = String(require("@openai/codex/package.json").version);
9
+ /** 输出当前版本,并在后台检查 npm 最新版本。 */
10
+ export function checkVersions() {
11
+ const localCodexVersion = commandVersion("codex");
12
+ logger.info("Canvas Agent version", { version: VERSION });
13
+ logger.info("Bundled Codex version", { version: CODEX_VERSION });
14
+ logger.info("Local Codex version", { version: localCodexVersion || "not found" });
15
+ if (!localCodexVersion) {
16
+ logger.warn("Local Codex was not found. Install the latest version with: npm install -g @openai/codex@latest");
17
+ }
18
+ else if (localCodexVersion !== CODEX_VERSION) {
19
+ logger.warn(`Bundled Codex ${CODEX_VERSION} does not match local Codex ${localCodexVersion}. Keep both current with: npm install -g @openai/codex@latest && npx -y @dream-craft/canvas-agent@latest`);
20
+ }
21
+ void checkLatestVersions(localCodexVersion);
22
+ }
23
+ /** 查询 npm,提醒升级不再维护的旧版本。 */
24
+ async function checkLatestVersions(localCodexVersion) {
25
+ try {
26
+ const [latestAgent, latestCodex] = await Promise.all([
27
+ npmVersion("@dream-craft/canvas-agent"),
28
+ npmVersion("@openai/codex"),
29
+ ]);
30
+ if (isOlder(VERSION, latestAgent))
31
+ logger.warn(`Update available: Canvas Agent ${VERSION} -> ${latestAgent}. Run: npx -y @dream-craft/canvas-agent@latest`);
32
+ if (isOlder(CODEX_VERSION, latestCodex))
33
+ logger.warn(`Update available: bundled Codex ${CODEX_VERSION} -> ${latestCodex}. Upgrade Canvas Agent with: npx -y @dream-craft/canvas-agent@latest`);
34
+ if (localCodexVersion && isOlder(localCodexVersion, latestCodex))
35
+ logger.warn(`Update available: local Codex ${localCodexVersion} -> ${latestCodex}. Run: npm install -g @openai/codex@latest`);
36
+ }
37
+ catch {
38
+ logger.warn("Unable to check the latest npm versions; startup will continue.");
39
+ }
40
+ }
41
+ /** 读取本机命令输出中的语义版本号。 */
42
+ function commandVersion(command) {
43
+ try {
44
+ return execFileSync(command, ["--version"], { encoding: "utf8", timeout: 5_000 }).match(/\d+\.\d+\.\d+/)?.[0] || "";
45
+ }
46
+ catch {
47
+ return "";
48
+ }
49
+ }
50
+ /** 读取 npm 包的最新版本。 */
51
+ async function npmVersion(name) {
52
+ const command = process.platform === "win32" ? "npm.cmd" : "npm";
53
+ const { stdout } = await execFileAsync(command, ["view", name, "version"], { encoding: "utf8", timeout: 10_000 });
54
+ return stdout.trim();
55
+ }
56
+ /** 比较仅包含数字段的稳定版语义版本。 */
57
+ function isOlder(current, latest) {
58
+ const left = current.split(".").map(Number);
59
+ const right = latest.split(".").map(Number);
60
+ for (let index = 0; index < Math.max(left.length, right.length); index++) {
61
+ if ((left[index] || 0) !== (right[index] || 0))
62
+ return (left[index] || 0) < (right[index] || 0);
63
+ }
64
+ return false;
65
+ }
package/package.json CHANGED
@@ -1,6 +1,46 @@
1
- {
2
- "name": "@dream-craft/canvas-agent",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
1
+ {
2
+ "name": "@dream-craft/canvas-agent",
3
+ "version": "0.6.4",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "canvas-agent": "dist/index.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "agent-instructions.md",
14
+ "README.md"
15
+ ],
16
+ "scripts": {
17
+ "dev": "tsx src/index.ts",
18
+ "debug": "tsx src/index.ts --debug",
19
+ "test": "tsx --test src/config.test.ts src/canvas/operations.test.ts src/canvas/session.test.ts src/agent/codex-client.test.ts src/agent/codex-history.test.ts src/agent/message-metadata.test.ts src/skills/store.test.ts src/utils/agent-runtime.test.ts",
20
+ "build": "tsc -p tsconfig.json",
21
+ "start": "node dist/index.js",
22
+ "prepack": "npm run build"
23
+ },
24
+ "dependencies": {
25
+ "@modelcontextprotocol/sdk": "^1.31.0",
26
+ "@openai/codex": "0.146.0",
27
+ "express": "^5.1.0",
28
+ "gray-matter": "^4.0.3",
29
+ "strip-ansi": "7.2.0",
30
+ "winston": "^3.19.0",
31
+ "yaml": "^2.9.0",
32
+ "zod": "^3.25.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/express": "^5.0.0",
36
+ "@types/node": "^22.0.0",
37
+ "tsx": "^4.19.0",
38
+ "typescript": "^5.8.0"
39
+ },
40
+ "engines": {
41
+ "node": ">=18"
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ }
46
+ }