@adep/runtime 0.1.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.
@@ -0,0 +1,27 @@
1
+ /**
2
+ * 能力运输键常量(CORE-018 上移自 functions 域):
3
+ * RPC 能力标记 + 链式命令通道标记 + 方法码。
4
+ *
5
+ * **纯常量文件,无类 / 无 parameter properties**——worker 侧用 strip-only 模式转译钟 import 本文件,
6
+ * 故绝不能在此引入 `ExecutorError`(见 `executor-runtime.ts` 头注释的边界)。
7
+ * 消费方(storage / database / realtime / mcp、functions 的 worker)经 `shared/` 依赖。
8
+ */
9
+ /** 平坦式 RPC 能力标记:值含该属性的 capability 视为命令通道能力(ST-001 命令通道设计)。 */
10
+ export declare const RPC_CAPABILITY_KEY: "__adepRpc";
11
+ /** 链式能力的标记键(与 `RPC_CAPABILITY_KEY` 并列,CORE-006 能力运输的第二形态)。 */
12
+ export declare const CHAIN_CAPABILITY_KEY: "__adepChain";
13
+ /** 链式能力与其他能力的传输方法码(worker ↔ 宿主 db handler 共享)。 */
14
+ export declare const DB_RPC: {
15
+ /** 直通方法(如 query):`(method=query, args=[sql, params])`。 */
16
+ readonly query: "query";
17
+ /** 读取 owned 表变更流(DB-006):`(method=changes, args=[table, query])`。 */
18
+ readonly changes: "changes";
19
+ /** 开启事务:`begin → txId`。 */
20
+ readonly begin: "begin";
21
+ /** 提交事务:`commit, args=[txId]`。 */
22
+ readonly commit: "commit";
23
+ /** 回滚事务:`rollback, args=[txId]`。 */
24
+ readonly rollback: "rollback";
25
+ /** 执行一条链:`chain, args=[ChainRequest]`。 */
26
+ readonly chain: "chain";
27
+ };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 执行器运行时契约(CORE-018 上移自 functions 域):错误类型与限额错误码。
3
+ *
4
+ * 独立成文件的原因(承自 functions/runtime/rpc-key.ts 的教训):worker 侧用 strip-only 模式
5
+ * 转译(不支持构造函数参数属性),任何被 worker 间接 import 的模块都不能带 `ExecutorError` 的
6
+ * parameter properties——故本文件与纯常量的 `capability-keys.ts` 分离,worker 只 import 后者。
7
+ *
8
+ * 消费方(functions / realtime / mcp)经 `shared/` 依赖,不再跨域 import functions 内部实现。
9
+ */
10
+ /** 执行失败的统一形状(网关回 504/500 信封)。 */
11
+ export declare class ExecutorError extends Error {
12
+ readonly status: number;
13
+ readonly code: string;
14
+ constructor(status: number, code: string, message: string);
15
+ }
16
+ /** 超时错误码(FN-002 限额:超时 → 504 级执行失败)。 */
17
+ export declare const TIMEOUT_CODE = "FN_EXEC_TIMEOUT";
18
+ /** 内存耗尽错误码(FN-002 限额:OOM → 5xx 级执行失败)。 */
19
+ export declare const OOM_CODE = "FN_EXEC_OOM";
20
+ /** 执行超时缺省值(毫秒)。 */
21
+ export declare const DEFAULT_TIMEOUT_MS = 10000;
22
+ /** 内存上限缺省值(MB)。 */
23
+ export declare const DEFAULT_MEMORY_LIMIT_MB = 128;
24
+ /** 可作为函数错误状态的合法 HTTP 码区间(FN-011:业务可表达 4xx/5xx 语义)。 */
25
+ export declare function isHttpStatus(status: unknown): status is number;
26
+ /**
27
+ * 函数抛错携带的 status 归一化(FN-011 error status pass-through)。
28
+ * 合法 4xx/5xx 整数原样返回;缺失 / 非法一律折叠为默认 500(兼容旧形态——普通 Error 抛错仍 500)。
29
+ */
30
+ export declare function normalizeHttpStatus(status: unknown): number;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * 函数服务源码解析(CORE-018 上移自 functions/runtime/forward.ts)。
3
+ *
4
+ * 被网关转发链与 MCP 工具发布复用「读当前服务源码」这一行为:发布版本优先、无则草稿。
5
+ * **松耦合**:只依赖最小结构接口(functionFiles / functionVersions 的读取面),
6
+ * 不 import `PlatformDb` / functions 域内部——消费方(gateway / mcp)传入自己的 db 即结构兼容。
7
+ *
8
+ * 纯函数 + 结构接口,零运行时依赖(规范 §4,shared 纯性)。
9
+ */
10
+ /** `resolveFunctionSource` 需要的最小 DB 读取面:只声明用到的两个仓库方法。结构兼容 `PlatformDb`。 */
11
+ export interface FunctionSourceDb {
12
+ readonly functionFiles: {
13
+ /** 按路径升序返回草稿文件组;无草稿返回空数组。 */
14
+ listByFunction(functionId: string): Promise<ReadonlyArray<{
15
+ path: string;
16
+ content: string;
17
+ }>>;
18
+ };
19
+ readonly functionVersions: {
20
+ /** 按函数 + 版本号精确读取;不存在返回 null。 */
21
+ findByFunctionAndVersion(functionId: string, version: number): Promise<{
22
+ code: string;
23
+ } | null>;
24
+ };
25
+ }
26
+ /** `resolveFunctionSource` 需要的函数投影:id(读草稿)与服务版本号。 */
27
+ export interface SourceFunction {
28
+ id: string;
29
+ /** 已发布版本号;`null` / 缺省 = 服务草稿(兼容 FunctionRecord 的 nullable 字段)。 */
30
+ publishedVersion?: number | null;
31
+ }
32
+ /**
33
+ * 解析函数当前服务源码(发布版本优先,无则草稿)。
34
+ * - 已发布(publishedVersion 非空):读不可变发布版本;该版本丢失(已裁剪)则降级草稿。切换是「读时判定」,
35
+ * 天然原子——发布/回滚对在途请求不产生 5xx(验收「发布不中断」)。
36
+ * - 未发布:读草稿源码组,无草稿返回 null。
37
+ * @returns 文件映射;函数没有任何可执行源码时返回 null。
38
+ */
39
+ export declare function resolveFunctionSource(db: FunctionSourceDb, fn: SourceFunction): Promise<Record<string, string> | null>;
40
+ /**
41
+ * 把版本行 code 还原成 files 映射(网关转发给 worker)。
42
+ * 独立于此文件避免引入 functions 域(快照序列化/哈希在 functions/publish/snapshot)。
43
+ */
44
+ export declare function parseSnapshot(code: string): Record<string, string>;
@@ -0,0 +1,11 @@
1
+ import type { CapabilityBundle } from '@adep/types';
2
+ import type { StorageDriver, StoredFileMeta } from './driver';
3
+ import type { DownloadSignerConfig } from './signature';
4
+ import type { StorageUploadData, StoredFile } from '@adep/types';
5
+ /** 把 CloudStorage 的上传数据类型收敛为 driver.put 需要的字节串(导出供 handler 与单测复用)。 */
6
+ export declare function asBytes(data: StorageUploadData): Uint8Array;
7
+ export declare function toStoredFile(meta: StoredFileMeta): StoredFile;
8
+ /**
9
+ * 按项目产出一组 `cloud.storage` 能力。`projectId` 绑定在装配期,worker 内免传。
10
+ */
11
+ export declare function createStorageCapability(driver: StorageDriver, signer: DownloadSignerConfig, projectId: string): CapabilityBundle;
@@ -0,0 +1,13 @@
1
+ import type { StorageDriver } from '../driver';
2
+ export interface LocalStorageOptions {
3
+ /** 数据根目录(config 的 STORAGE_DIR)。 */
4
+ dir: string;
5
+ /** 项目配额字节;缺省 1GiB(PRD §2.4)。测试可注入小值验证超限。 */
6
+ quotaBytes?: number;
7
+ /**
8
+ * BILL-005:项目级配额回调(billing 域注入)。传入项目净增字节(覆盖写按净增量计),
9
+ * 超限时**抛错**(billing 的 BILLING_QUOTA_EXCEEDED)。缺省走静态 `quotaBytes` 判定。
10
+ */
11
+ quotaCheck?: (projectId: string, projectedBytes: number) => Promise<void>;
12
+ }
13
+ export declare function createLocalStorageDriver(options: LocalStorageOptions): StorageDriver;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * StorageDriver 接口(ST-001 Definition 层):对象存储的能力缝。
3
+ *
4
+ * 「能力缝」意味实现可替换:M1 用本地磁盘(driver/local.ts),S3 驱动后续接入(tech-stack §2.6),
5
+ * 平台路由与 cloud SDK 只依赖本接口,不感知底层。
6
+ *
7
+ * **契约集合(对齐 `@adep/types` 的 `CloudStorage`,并补 M1 平台需要的元数据与配额)**:
8
+ * - 路径一律是**项目桶内相对路径**(如 `avatars/avatar.png`),禁止绝对路径 / `../` 穿越,
9
+ * 非法路径抛 `STORAGE_INVALID_PATH`(验收 Scenario 4);
10
+ * - 文件级 `visibility`:public 直连、private 签名 URL(15 分钟,验收 Scenario 1/2);
11
+ * - 项目配额:超限抛 `STORAGE_QUOTA_EXCEEDED`。
12
+ * 统一异常形状 `StorageError`(status + code + message),路由层据此回规范 §5 错误信封。
13
+ */
14
+ /** 项目公桶配额(PRD §2.4:1GB/项目;local 实现按目录递归求 total size 判定)。 */
15
+ export declare const PROJECT_QUOTA_BYTES: number;
16
+ export type FileVisibility = 'public' | 'private';
17
+ /** 存储对象的元数据(下载 / 列表 / 签名用;不含内容体)。 */
18
+ export interface StoredFileMeta {
19
+ /** 桶内相对路径。 */
20
+ readonly path: string;
21
+ readonly size: number;
22
+ readonly contentType?: string;
23
+ readonly visibility: FileVisibility;
24
+ /** ISO 8601。 */
25
+ readonly updatedAt: string;
26
+ }
27
+ /** 写入选项。 */
28
+ export interface PutOptions {
29
+ visibility: FileVisibility;
30
+ contentType?: string;
31
+ }
32
+ /** 读取结果:内容 + 元数据(签名验证 / Content-Type 回复要用 meta)。 */
33
+ export interface GetResult {
34
+ data: Uint8Array;
35
+ meta: StoredFileMeta;
36
+ }
37
+ export interface StorageDriver {
38
+ /** 上传 / 覆盖文件;非法路径抛 `STORAGE_INVALID_PATH`,超配额抛 `STORAGE_QUOTA_EXCEEDED`。 */
39
+ put(projectId: string, path: string, data: Uint8Array, options: PutOptions): Promise<StoredFileMeta>;
40
+ /** 读取文件;不存在抛 `STORAGE_NOT_FOUND`。 */
41
+ get(projectId: string, path: string): Promise<GetResult>;
42
+ /** 读取元数据(不读内容;签名校验先查 visibility)。 */
43
+ getMeta(projectId: string, path: string): Promise<StoredFileMeta>;
44
+ /** 删除文件;不存在抛 `STORAGE_NOT_FOUND`。 */
45
+ remove(projectId: string, path: string): Promise<void>;
46
+ /** 按前缀列举(缺省全桶);排除平台元数据文件。 */
47
+ list(projectId: string, prefix?: string): Promise<StoredFileMeta[]>;
48
+ /** 当前项目已用字节数(配额判定的依据)。 */
49
+ usage(projectId: string): Promise<number>;
50
+ }
51
+ /** ST-001 统一存储异常。 */
52
+ export declare class StorageError extends Error {
53
+ readonly status: number;
54
+ readonly code: string;
55
+ constructor(status: number, code: string, message: string);
56
+ }
57
+ export declare const STORAGE_CODES: {
58
+ readonly invalidPath: "STORAGE_INVALID_PATH";
59
+ readonly notFound: "STORAGE_NOT_FOUND";
60
+ readonly quotaExceeded: "STORAGE_QUOTA_EXCEEDED";
61
+ };
62
+ /**
63
+ * 路径穿越防护(验收 Scenario 4):拒绝绝对路径、`..` 段、空路径、Windows 盘符、控制字符。
64
+ * 合法路径为单层或多层相对段(如 `a`、`a/b.png`),每段不能是 `.`/`..`、空或含路径分隔符。
65
+ */
66
+ export declare function assertSafeStoragePath(path: string): string;
@@ -0,0 +1,23 @@
1
+ export interface DownloadSignerConfig {
2
+ /** 平台配置的签名密钥(config.ts 复用 AUTH_SECRET 即可;不入库、不输出)。 */
3
+ secret: string;
4
+ /** 生成完整外链的基址(config.ts 的 AUTH_URL / PLATFORM_DOMAIN)。 */
5
+ baseUrl: string;
6
+ }
7
+ /** M1 签名有效期(PRD §2.4 / ST-001 任务单:15 分钟)。 */
8
+ export declare const DEFAULT_SIGN_TTL_SECONDS: number;
9
+ export declare const SIGN_EXPIRES_KEY = "x-expires";
10
+ export declare const SIGN_SIGNATURE_KEY = "x-signature";
11
+ /** 生成私有文件的外链(含签名查询参数)。 */
12
+ export declare function signDownloadUrl(config: DownloadSignerConfig, projectId: string, path: string, ttlSeconds?: number): string;
13
+ export type SignatureVerification = {
14
+ ok: true;
15
+ } | {
16
+ ok: false;
17
+ reason: 'missing' | 'malformed' | 'expired' | 'invalid';
18
+ };
19
+ /** 校验签名 URL;`nowSeconds` 可注入(单测模拟过期)。 */
20
+ export declare function verifyDownloadSignature(config: DownloadSignerConfig, projectId: string, path: string, query: {
21
+ expires?: unknown;
22
+ signature?: unknown;
23
+ }, nowSeconds?: number): SignatureVerification;
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@adep/runtime",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "description": "AgentDeploy 运行时内核:云函数执行器 + 本地模拟运行时 + cloud.db/cloud.storage 能力装配,零平台重栈依赖(无 elysia/drizzle/better-auth/nuxt/bun:sqlite/postgres/ioredis),供 server / CLI(adep dev) / 浏览器离线工作区三方复用。",
8
+ "main": "./src/index.ts",
9
+ "types": "./src/index.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./src/index.ts",
13
+ "default": "./src/index.ts"
14
+ },
15
+ "./*": {
16
+ "types": "./src/*.ts",
17
+ "default": "./src/*.ts"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "scripts": {
24
+ "test": "vitest run",
25
+ "build": "bun run ../../scripts/build-package.ts runtime"
26
+ },
27
+ "dependencies": {
28
+ "@adep/types": "workspace:*"
29
+ },
30
+ "publishConfig": {
31
+ "main": "./dist/index.js",
32
+ "types": "./dist/index.d.ts",
33
+ "exports": {
34
+ ".": {
35
+ "types": "./dist/index.d.ts",
36
+ "default": "./dist/index.js"
37
+ },
38
+ "./*": {
39
+ "types": "./dist/*.d.ts",
40
+ "default": "./dist/*.js"
41
+ }
42
+ }
43
+ }
44
+ }