@coralai/sps-cli 0.85.0 → 0.86.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/assembly/base.yml CHANGED
@@ -99,6 +99,11 @@
99
99
  # 🔴 真源是装配档那一行的 config,**不另起一份** —— 两个真源最难查。
100
100
  name: '@coralai/sps-cli/seams/settings'
101
101
 
102
+ - id: storage
103
+ # 对象存储(读/列/写):插件读写桶,不必自带 S3 客户端。
104
+ # ⚠️ 权限按前缀分且很紧 —— sps 今天的 key 只够 assets/;读不了会抛,不回空。
105
+ name: '@coralai/sps-cli/seams/storage'
106
+
102
107
  - id: jobs
103
108
  # 后台任务表:async 能力把长任务丢进它,拿 handle,之后 poll。
104
109
  # ⚠️ **在内存里**,tick 进程重启 ⇒ handle 丢 ⇒ poll 当场说清楚(不是一直 done:false)。
@@ -10,5 +10,7 @@ export declare class FakeStorage implements StorageBackend {
10
10
  failNext: string | null;
11
11
  put(key: string, bytes: Buffer, contentType?: string): Promise<void>;
12
12
  list(prefix: string): Promise<StorageObject[]>;
13
+ /** 没有这个 key ⇒ `null`(与真后端同语义:不抛)。 */
14
+ get(key: string): Promise<Buffer | null>;
13
15
  }
14
16
  //# sourceMappingURL=FakeStorage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FakeStorage.d.ts","sourceRoot":"","sources":["../../../src/providers/storage/FakeStorage.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAA2B,MAAM,qBAAqB,CAAC;AAEvG,qBAAa,WAAY,YAAW,cAAc;IAChD,QAAQ,CAAC,OAAO;eAA4B,MAAM;sBAAgB,MAAM;cAAQ,MAAM;OAAM;IAC5F,QAAQ,EAAE,MAAM,EAAE,CAAM;IACxB,mCAAmC;IACnC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEzB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUpE,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;CAKrD"}
1
+ {"version":3,"file":"FakeStorage.d.ts","sourceRoot":"","sources":["../../../src/providers/storage/FakeStorage.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAA2B,MAAM,qBAAqB,CAAC;AAEvG,qBAAa,WAAY,YAAW,cAAc;IAChD,QAAQ,CAAC,OAAO;eAA4B,MAAM;sBAAgB,MAAM;cAAQ,MAAM;OAAM;IAC5F,QAAQ,EAAE,MAAM,EAAE,CAAM;IACxB,mCAAmC;IACnC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEzB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUpE,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAMpD,qCAAqC;IAC/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAG/C"}
@@ -29,5 +29,9 @@ export class FakeStorage {
29
29
  .filter(([k]) => k.startsWith(prefix))
30
30
  .map(([key, v]) => ({ key, etag: v.etag, size: v.bytes.length }));
31
31
  }
32
+ /** 没有这个 key ⇒ `null`(与真后端同语义:不抛)。 */
33
+ async get(key) {
34
+ return this.objects.get(key)?.bytes ?? null;
35
+ }
32
36
  }
33
37
  //# sourceMappingURL=FakeStorage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FakeStorage.js","sourceRoot":"","sources":["../../../src/providers/storage/FakeStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAA2C,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAEvG,MAAM,OAAO,WAAW;IACb,OAAO,GAAG,IAAI,GAAG,EAAiE,CAAC;IAC5F,QAAQ,GAAa,EAAE,CAAC;IACxB,mCAAmC;IACnC,QAAQ,GAAkB,IAAI,CAAC;IAE/B,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAa,EAAE,WAAoB;QACxD,IAAI,IAAI,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC;YAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACrB,MAAM,IAAI,uBAAuB,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,uDAAuD;QACvD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrG,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc;QACvB,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;aAC/B,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;aACrC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACtE,CAAC;CACF"}
1
+ {"version":3,"file":"FakeStorage.js","sourceRoot":"","sources":["../../../src/providers/storage/FakeStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAA2C,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAEvG,MAAM,OAAO,WAAW;IACb,OAAO,GAAG,IAAI,GAAG,EAAiE,CAAC;IAC5F,QAAQ,GAAa,EAAE,CAAC;IACxB,mCAAmC;IACnC,QAAQ,GAAkB,IAAI,CAAC;IAE/B,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAa,EAAE,WAAoB;QACxD,IAAI,IAAI,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC;YAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACrB,MAAM,IAAI,uBAAuB,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,uDAAuD;QACvD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrG,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc;QACvB,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;aAC/B,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;aACrC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,qCAAqC;IACrC,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC;IAC9C,CAAC;CACF"}
@@ -27,5 +27,15 @@ export declare class MinioBackend implements StorageBackend {
27
27
  private ensure;
28
28
  put(key: string, bytes: Buffer, contentType?: string): Promise<void>;
29
29
  list(prefix: string): Promise<StorageObject[]>;
30
+ /**
31
+ * 读一个对象。
32
+ *
33
+ * 🔴 **"没有这个 key" 与 "读不了" 必须分开**:
34
+ * 前者返回 `null`(调用方据此走兜底),后者抛 `StorageUnavailableError`。
35
+ * 混成一个的表现是"库是空的" —— 而真相可能是**权限不够**,
36
+ * 那会让人去补素材而不是去补策略。
37
+ * MinIO 的 NoSuchKey 走 code,不看消息文本(消息会随版本变)。
38
+ */
39
+ get(key: string): Promise<Buffer | null>;
30
40
  }
31
41
  //# sourceMappingURL=MinioBackend.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MinioBackend.d.ts","sourceRoot":"","sources":["../../../src/providers/storage/MinioBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAcxD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAElD;AAED,qBAAa,YAAa,YAAW,cAAc;IAGrC,OAAO,CAAC,QAAQ,CAAC,GAAG;IAFhC,OAAO,CAAC,MAAM,CAA0B;gBAEX,GAAG,EAAE,aAAa;YAEjC,MAAM;IAwBd,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAapE,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;CAgBrD"}
1
+ {"version":3,"file":"MinioBackend.d.ts","sourceRoot":"","sources":["../../../src/providers/storage/MinioBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAexD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAElD;AAED,qBAAa,YAAa,YAAW,cAAc;IAGrC,OAAO,CAAC,QAAQ,CAAC,GAAG;IAFhC,OAAO,CAAC,MAAM,CAA0B;gBAEX,GAAG,EAAE,aAAa;YAEjC,MAAM;IAwBd,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAapE,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAiBpD;;;;;;;;OAQG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAa/C"}
@@ -56,5 +56,30 @@ export class MinioBackend {
56
56
  stream.on('error', (e) => reject(new StorageUnavailableError(`列举失败:${prefix}`, e)));
57
57
  });
58
58
  }
59
+ /**
60
+ * 读一个对象。
61
+ *
62
+ * 🔴 **"没有这个 key" 与 "读不了" 必须分开**:
63
+ * 前者返回 `null`(调用方据此走兜底),后者抛 `StorageUnavailableError`。
64
+ * 混成一个的表现是"库是空的" —— 而真相可能是**权限不够**,
65
+ * 那会让人去补素材而不是去补策略。
66
+ * MinIO 的 NoSuchKey 走 code,不看消息文本(消息会随版本变)。
67
+ */
68
+ async get(key) {
69
+ const c = await this.ensure();
70
+ try {
71
+ const stream = await c.getObject(this.cfg.bucket, key);
72
+ const chunks = [];
73
+ for await (const ch of stream)
74
+ chunks.push(ch);
75
+ return Buffer.concat(chunks);
76
+ }
77
+ catch (e) {
78
+ const code = e.code;
79
+ if (code === 'NoSuchKey' || code === 'NotFound')
80
+ return null;
81
+ throw new StorageUnavailableError(`读取失败:${key}`, e);
82
+ }
83
+ }
59
84
  }
60
85
  //# sourceMappingURL=MinioBackend.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MinioBackend.js","sourceRoot":"","sources":["../../../src/providers/storage/MinioBackend.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MinioBackend.js","sourceRoot":"","sources":["../../../src/providers/storage/MinioBackend.ts"],"names":[],"mappings":"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"}
@@ -34,6 +34,15 @@ export interface StorageBackend {
34
34
  put(key: string, bytes: Buffer, contentType?: string): Promise<void>;
35
35
  /** 列一个前缀下的全部对象(递归)。前缀为空即整桶 —— 调用方自己收窄。 */
36
36
  list(prefix: string): Promise<StorageObject[]>;
37
+ /**
38
+ * 读一个对象。
39
+ *
40
+ * 🔴 **不存在返回 `null`,不抛** —— "有没有"是正常的问题
41
+ * (占位兜底就是先问"库里有没有")。而**连不上/没权限要抛**
42
+ * `StorageUnavailableError`:那两件事和"这个 key 没有"完全不同,
43
+ * 混在一起的表现是"库是空的",而真相是这个 key 读不了。
44
+ */
45
+ get(key: string): Promise<Buffer | null>;
37
46
  }
38
47
  /** 后端不可用时抛这个,**不要静默降级**成"这轮没东西同步"。 */
39
48
  export declare class StorageUnavailableError extends Error {
@@ -1 +1 @@
1
- {"version":3,"file":"StorageBackend.d.ts","sourceRoot":"","sources":["../../../src/providers/storage/StorageBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,oDAAoD;AACpD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B;;;;;;OAMG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErE,0CAA0C;IAC1C,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;CAChD;AAED,sCAAsC;AACtC,qBAAa,uBAAwB,SAAQ,KAAK;IACnB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;gBAAzC,OAAO,EAAE,MAAM,EAAW,KAAK,CAAC,EAAE,OAAO,YAAA;CAItD"}
1
+ {"version":3,"file":"StorageBackend.d.ts","sourceRoot":"","sources":["../../../src/providers/storage/StorageBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,oDAAoD;AACpD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B;;;;;;OAMG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErE,0CAA0C;IAC1C,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAE/C;;;;;;;OAOG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC1C;AAED,sCAAsC;AACtC,qBAAa,uBAAwB,SAAQ,KAAK;IACnB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;gBAAzC,OAAO,EAAE,MAAM,EAAW,KAAK,CAAC,EAAE,OAAO,YAAA;CAItD"}
@@ -1 +1 @@
1
- {"version":3,"file":"StorageBackend.js","sourceRoot":"","sources":["../../../src/providers/storage/StorageBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAuBH,sCAAsC;AACtC,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACV;IAAtC,YAAY,OAAe,EAAW,KAAe;QACnD,KAAK,CAAC,OAAO,CAAC,CAAC;QADqB,UAAK,GAAL,KAAK,CAAU;QAEnD,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF"}
1
+ {"version":3,"file":"StorageBackend.js","sourceRoot":"","sources":["../../../src/providers/storage/StorageBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAiCH,sCAAsC;AACtC,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACV;IAAtC,YAAY,OAAe,EAAW,KAAe;QACnD,KAAK,CAAC,OAAO,CAAC,CAAC;QADqB,UAAK,GAAL,KAAK,CAAU;QAEnD,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @module seams/storage
3
+ * @description **对象存储 seam** —— 插件读写桶,不必自带 S3 客户端和一套凭据。
4
+ *
5
+ * @layer seam
6
+ *
7
+ * 类型:**甲 · 工厂型**(进程里一个实现)。
8
+ *
9
+ * 🔴 **"sps 不认识桶"这条前提在 2026-08-19 已被推翻**
10
+ * (`object-storage-and-workspace-sync.md` §2.1:对象存储改为 sps 的一项能力,sidecar 退役)。
11
+ * 理由是多节点下 studio / coral 都不在工作区那台机器上,唯一共享面就是桶;
12
+ * 而"studio 点发布 → 请 sps 产出发布包并落桶"本身就已经要求 sps 往桶里写字节。
13
+ * ⚠️ 我的记忆一度停在推翻之前 —— 读到那条旧结论时要先核文档。
14
+ *
15
+ * 🔴 **它只做搬字节,不做账。** id / 索引 / 缩略图 / 分类 / 配额 / 计费 / undo 都在 studio ——
16
+ * 一进 sps,这个公共 npm 包就认识"用户"和"配额"了。
17
+ *
18
+ * ⚠️ **权限是按前缀分的,而且很紧**(单写方规则):
19
+ * sps 今天的 key 只够 `assets/`;`library/**` 实测 Access Denied。
20
+ * 所以这一层**不承诺你能读任何前缀** —— 读不了会抛,而不是回空。
21
+ * "库是空的"和"我没权限"混成一个,人会去补素材而不是去补策略。
22
+ */
23
+ import { type Context, Service } from '@deepseek-ai/cordis';
24
+ import type { StorageObject } from '../../providers/storage/StorageBackend.js';
25
+ export declare const STORAGE = "sps.storage";
26
+ export declare const category = "\u5B58\u50A8";
27
+ export declare const description = "\u5BF9\u8C61\u5B58\u50A8(\u8BFB/\u5217/\u5199):\u63D2\u4EF6\u8BFB\u5199\u6876,\u4E0D\u5FC5\u81EA\u5E26 S3 \u5BA2\u6237\u7AEF\u3002";
28
+ export default class StorageSeam extends Service {
29
+ constructor(ctx: Context);
30
+ /**
31
+ * 桶配没配。**没配时 `get`/`list`/`put` 会抛** —— 插件应当先问这一句,
32
+ * 而不是拿异常当分支(那样"没配"和"读不了"在日志里长得一样)。
33
+ */
34
+ configured(): boolean;
35
+ /** 读一个对象。不存在 ⇒ `null`;连不上/没权限 ⇒ **抛**。 */
36
+ get(key: string): Promise<Buffer | null>;
37
+ /** 列一个前缀。 */
38
+ list(prefix: string): Promise<StorageObject[]>;
39
+ /**
40
+ * 写一个对象。
41
+ * ⚠️ `contentType` 拿不准时**自己决定**,别指望后端猜 ——
42
+ * 桶是直连的,缺省的 octet-stream 会让预览变成一次下载。
43
+ */
44
+ put(key: string, bytes: Buffer, contentType?: string): Promise<void>;
45
+ private backend;
46
+ private must;
47
+ }
48
+ declare module '@deepseek-ai/cordis' {
49
+ interface Context {
50
+ 'sps.storage': StorageSeam;
51
+ }
52
+ }
53
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/seams/storage/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,KAAK,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE5D,OAAO,KAAK,EAAkB,aAAa,EAAE,MAAM,2CAA2C,CAAC;AAG/F,eAAO,MAAM,OAAO,gBAAgB,CAAC;AAErC,eAAO,MAAM,QAAQ,iBAAO,CAAC;AAC7B,eAAO,MAAM,WAAW,uIAAmC,CAAC;AAE5D,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,OAAO;gBAClC,GAAG,EAAE,OAAO;IAIxB;;;OAGG;IACH,UAAU,IAAI,OAAO;IAIrB,0CAA0C;IACpC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAI9C,aAAa;IACP,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAIpD;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1E,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,IAAI;CAOb;AAGD,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,aAAa,EAAE,WAAW,CAAC;KAC5B;CACF"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @module seams/storage
3
+ * @description **对象存储 seam** —— 插件读写桶,不必自带 S3 客户端和一套凭据。
4
+ *
5
+ * @layer seam
6
+ *
7
+ * 类型:**甲 · 工厂型**(进程里一个实现)。
8
+ *
9
+ * 🔴 **"sps 不认识桶"这条前提在 2026-08-19 已被推翻**
10
+ * (`object-storage-and-workspace-sync.md` §2.1:对象存储改为 sps 的一项能力,sidecar 退役)。
11
+ * 理由是多节点下 studio / coral 都不在工作区那台机器上,唯一共享面就是桶;
12
+ * 而"studio 点发布 → 请 sps 产出发布包并落桶"本身就已经要求 sps 往桶里写字节。
13
+ * ⚠️ 我的记忆一度停在推翻之前 —— 读到那条旧结论时要先核文档。
14
+ *
15
+ * 🔴 **它只做搬字节,不做账。** id / 索引 / 缩略图 / 分类 / 配额 / 计费 / undo 都在 studio ——
16
+ * 一进 sps,这个公共 npm 包就认识"用户"和"配额"了。
17
+ *
18
+ * ⚠️ **权限是按前缀分的,而且很紧**(单写方规则):
19
+ * sps 今天的 key 只够 `assets/`;`library/**` 实测 Access Denied。
20
+ * 所以这一层**不承诺你能读任何前缀** —— 读不了会抛,而不是回空。
21
+ * "库是空的"和"我没权限"混成一个,人会去补素材而不是去补策略。
22
+ */
23
+ import { Service } from '@deepseek-ai/cordis';
24
+ import { MinioBackend } from '../../providers/storage/MinioBackend.js';
25
+ import { activeStorageConfig } from '../../providers/storage/storageConfig.js';
26
+ export const STORAGE = 'sps.storage';
27
+ export const category = '存储';
28
+ export const description = '对象存储(读/列/写):插件读写桶,不必自带 S3 客户端。';
29
+ export default class StorageSeam extends Service {
30
+ constructor(ctx) {
31
+ super(ctx, STORAGE);
32
+ }
33
+ /**
34
+ * 桶配没配。**没配时 `get`/`list`/`put` 会抛** —— 插件应当先问这一句,
35
+ * 而不是拿异常当分支(那样"没配"和"读不了"在日志里长得一样)。
36
+ */
37
+ configured() {
38
+ return this.backend() !== null;
39
+ }
40
+ /** 读一个对象。不存在 ⇒ `null`;连不上/没权限 ⇒ **抛**。 */
41
+ async get(key) {
42
+ return this.must().get(key);
43
+ }
44
+ /** 列一个前缀。 */
45
+ async list(prefix) {
46
+ return this.must().list(prefix);
47
+ }
48
+ /**
49
+ * 写一个对象。
50
+ * ⚠️ `contentType` 拿不准时**自己决定**,别指望后端猜 ——
51
+ * 桶是直连的,缺省的 octet-stream 会让预览变成一次下载。
52
+ */
53
+ async put(key, bytes, contentType) {
54
+ return this.must().put(key, bytes, contentType);
55
+ }
56
+ backend() {
57
+ // 每次现取:改了配置不用重挂插件(同 credentials 那条理由)
58
+ const cfg = activeStorageConfig();
59
+ return cfg ? new MinioBackend(cfg) : null;
60
+ }
61
+ must() {
62
+ const b = this.backend();
63
+ if (!b) {
64
+ throw new Error('对象存储没配(~/.coral/storage.json)—— 先用 configured() 问一句');
65
+ }
66
+ return b;
67
+ }
68
+ }
69
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/seams/storage/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAgB,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAEvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAE/E,MAAM,CAAC,MAAM,OAAO,GAAG,aAAa,CAAC;AAErC,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC;AAC7B,MAAM,CAAC,MAAM,WAAW,GAAG,gCAAgC,CAAC;AAE5D,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,OAAO;IAC9C,YAAY,GAAY;QACtB,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACtB,CAAC;IAED;;;OAGG;IACH,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,CAAC;IACjC,CAAC;IAED,0CAA0C;IAC1C,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,aAAa;IACb,KAAK,CAAC,IAAI,CAAC,MAAc;QACvB,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAa,EAAE,WAAoB;QACxD,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;IAClD,CAAC;IAEO,OAAO;QACb,sCAAsC;QACtC,MAAM,GAAG,GAAG,mBAAmB,EAAE,CAAC;QAClC,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5C,CAAC;IAEO,IAAI;QACV,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coralai/sps-cli",
3
- "version": "0.85.0",
3
+ "version": "0.86.0",
4
4
  "description": "SPS CLI — AI-driven development pipeline orchestrator",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",