@coralai/sps-cli 0.82.0 → 0.83.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: jobs
103
+ # 后台任务表:async 能力把长任务丢进它,拿 handle,之后 poll。
104
+ # ⚠️ **在内存里**,tick 进程重启 ⇒ handle 丢 ⇒ poll 当场说清楚(不是一直 done:false)。
105
+ name: '@coralai/sps-cli/seams/jobs'
106
+
102
107
  - id: cards
103
108
  # 卡片(建/列):插件按自己的规则建卡,sps 不必认识那些规则。
104
109
  # 🔴 起因是「manifest → 建几张卡」那段知识该住哪:住 sps 就要认识 gameforge 的概念,
@@ -0,0 +1,75 @@
1
+ /**
2
+ * @module seams/jobs
3
+ * @description **后台任务表** —— 长任务跑在后台,给个 handle,之后能问状态。
4
+ *
5
+ * @layer seam
6
+ *
7
+ * 类型:**乙 · 注册表型**(收一堆在跑的任务)。
8
+ *
9
+ * 🔴 **为什么它该在 sps,而不是每个插件自己维护一张表**:
10
+ * async 能力的 `start` 要"发起并立刻返回",`poll` 要"问完没完" ——
11
+ * 中间那张 handle 表是**纯机制、零领域知识**。
12
+ * 每个插件各造一份的话,`sps.jobs.poll` 的返回形状就是 `AsyncPoll` 这件事
13
+ * 要重复对齐 N 次,而且**重启那一格必然被忘掉**(见下)。
14
+ * 今天已经有两个消费方(gameforge 的生图、音频),不是为将来备的。
15
+ *
16
+ * 🔴 **在内存里,而且这是对的** —— `sps tick <project>` 是**常驻循环进程**
17
+ * (一个项目一个),start 与后续的 poll 在同一个进程里。
18
+ * 但它会被 stop / 重启 ⇒ **handle 会丢**。
19
+ * ⚠️ 丢了之后 `poll` 必须**当场说清楚**,不能回 `{done:false}` ——
20
+ * 后者的表现是卡片一直等到 30 分钟超时,然后被归因成"生图太慢",
21
+ * 而真因是进程重启过。**沉默的错误归因比失败本身更贵。**
22
+ *
23
+ * ⚠️ **不做持久化**。要持久就得有一张跨进程的任务表,那是另一个量级的东西
24
+ * (而且它得回答"重启后那个外部任务还在不在")。今天的答案是:
25
+ * 重启 ⇒ 那张卡失败并说明原因 ⇒ 重跑它。
26
+ */
27
+ import { type Context, Service } from '@deepseek-ai/cordis';
28
+ export declare const JOBS = "sps.jobs";
29
+ export declare const category = "\u4EFB\u52A1";
30
+ export declare const description = "\u540E\u53F0\u4EFB\u52A1\u8868:async \u80FD\u529B\u7528\u5B83\u628A\u957F\u4EFB\u52A1\u8DD1\u8D77\u6765\u5E76\u62FF\u5230 handle\u3002";
31
+ /** 与 `AsyncPoll` 同形 —— async 能力的 `poll` 可以直接把它透传出去。 */
32
+ export type JobStatus = {
33
+ done: false;
34
+ } | {
35
+ done: true;
36
+ ok: true;
37
+ result: Record<string, unknown>;
38
+ } | {
39
+ done: true;
40
+ ok: false;
41
+ error: string;
42
+ };
43
+ export default class JobsSeam extends Service {
44
+ private readonly jobs;
45
+ private seq;
46
+ constructor(ctx: Context);
47
+ /**
48
+ * 把一个长任务跑起来,**立刻**返回 handle。
49
+ *
50
+ * 🔴 `fn` 抛出**不会**冒泡到调用方 —— 它跑在后台,没人接得住。
51
+ * 抛的内容变成 `poll` 的 `error`。
52
+ */
53
+ start(fn: () => Promise<Record<string, unknown>>): string;
54
+ /**
55
+ * 问状态。
56
+ *
57
+ * 🔴 **不认识的 handle 当失败,不当"还在跑"** —— 见模块头那条:
58
+ * 回 `{done:false}` 会让卡片一直等到超时,然后被归因成"任务太慢"。
59
+ */
60
+ poll(handle: string): JobStatus;
61
+ /** 跑完的任务清掉,别让内存无限长。返回清掉几个。 */
62
+ reap(olderThanMs?: number): number;
63
+ /** 现在有几个在跑(诊断用)。 */
64
+ list(): {
65
+ handle: string;
66
+ done: boolean;
67
+ startedAt: number;
68
+ }[];
69
+ }
70
+ declare module '@deepseek-ai/cordis' {
71
+ interface Context {
72
+ 'sps.jobs': JobsSeam;
73
+ }
74
+ }
75
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/seams/jobs/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,KAAK,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE5D,eAAO,MAAM,IAAI,aAAa,CAAC;AAE/B,eAAO,MAAM,QAAQ,iBAAO,CAAC;AAC7B,eAAO,MAAM,WAAW,2IAAuC,CAAC;AAEhE,uDAAuD;AACvD,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,GACf;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAO7C,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,OAAO;IAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0B;IAC/C,OAAO,CAAC,GAAG,CAAK;gBAEJ,GAAG,EAAE,OAAO;IAIxB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM;IAczD;;;;;OAKG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IAY/B,8BAA8B;IAC9B,IAAI,CAAC,WAAW,SAAc,GAAG,MAAM;IAYvC,oBAAoB;IACpB,IAAI,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,EAAE;CAO/D;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,UAAU,EAAE,QAAQ,CAAC;KACtB;CACF"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * @module seams/jobs
3
+ * @description **后台任务表** —— 长任务跑在后台,给个 handle,之后能问状态。
4
+ *
5
+ * @layer seam
6
+ *
7
+ * 类型:**乙 · 注册表型**(收一堆在跑的任务)。
8
+ *
9
+ * 🔴 **为什么它该在 sps,而不是每个插件自己维护一张表**:
10
+ * async 能力的 `start` 要"发起并立刻返回",`poll` 要"问完没完" ——
11
+ * 中间那张 handle 表是**纯机制、零领域知识**。
12
+ * 每个插件各造一份的话,`sps.jobs.poll` 的返回形状就是 `AsyncPoll` 这件事
13
+ * 要重复对齐 N 次,而且**重启那一格必然被忘掉**(见下)。
14
+ * 今天已经有两个消费方(gameforge 的生图、音频),不是为将来备的。
15
+ *
16
+ * 🔴 **在内存里,而且这是对的** —— `sps tick <project>` 是**常驻循环进程**
17
+ * (一个项目一个),start 与后续的 poll 在同一个进程里。
18
+ * 但它会被 stop / 重启 ⇒ **handle 会丢**。
19
+ * ⚠️ 丢了之后 `poll` 必须**当场说清楚**,不能回 `{done:false}` ——
20
+ * 后者的表现是卡片一直等到 30 分钟超时,然后被归因成"生图太慢",
21
+ * 而真因是进程重启过。**沉默的错误归因比失败本身更贵。**
22
+ *
23
+ * ⚠️ **不做持久化**。要持久就得有一张跨进程的任务表,那是另一个量级的东西
24
+ * (而且它得回答"重启后那个外部任务还在不在")。今天的答案是:
25
+ * 重启 ⇒ 那张卡失败并说明原因 ⇒ 重跑它。
26
+ */
27
+ import { Service } from '@deepseek-ai/cordis';
28
+ export const JOBS = 'sps.jobs';
29
+ export const category = '任务';
30
+ export const description = '后台任务表:async 能力用它把长任务跑起来并拿到 handle。';
31
+ export default class JobsSeam extends Service {
32
+ jobs = new Map();
33
+ seq = 0;
34
+ constructor(ctx) {
35
+ super(ctx, JOBS);
36
+ }
37
+ /**
38
+ * 把一个长任务跑起来,**立刻**返回 handle。
39
+ *
40
+ * 🔴 `fn` 抛出**不会**冒泡到调用方 —— 它跑在后台,没人接得住。
41
+ * 抛的内容变成 `poll` 的 `error`。
42
+ */
43
+ start(fn) {
44
+ const handle = `job-${++this.seq}-${Date.now()}`;
45
+ const job = { status: { done: false }, startedAt: Date.now() };
46
+ this.jobs.set(handle, job);
47
+ void (async () => {
48
+ try {
49
+ job.status = { done: true, ok: true, result: await fn() };
50
+ }
51
+ catch (e) {
52
+ job.status = { done: true, ok: false, error: e instanceof Error ? e.message : String(e) };
53
+ }
54
+ })();
55
+ return handle;
56
+ }
57
+ /**
58
+ * 问状态。
59
+ *
60
+ * 🔴 **不认识的 handle 当失败,不当"还在跑"** —— 见模块头那条:
61
+ * 回 `{done:false}` 会让卡片一直等到超时,然后被归因成"任务太慢"。
62
+ */
63
+ poll(handle) {
64
+ const job = this.jobs.get(handle);
65
+ if (!job) {
66
+ return {
67
+ done: true,
68
+ ok: false,
69
+ error: `任务 ${handle} 不在任务表里 —— 多半是这个 tick 进程重启过(任务表在内存里)。重跑这张卡。`,
70
+ };
71
+ }
72
+ return job.status;
73
+ }
74
+ /** 跑完的任务清掉,别让内存无限长。返回清掉几个。 */
75
+ reap(olderThanMs = 60 * 60_000) {
76
+ const cutoff = Date.now() - olderThanMs;
77
+ let n = 0;
78
+ for (const [h, j] of this.jobs) {
79
+ if (j.status.done && j.startedAt < cutoff) {
80
+ this.jobs.delete(h);
81
+ n++;
82
+ }
83
+ }
84
+ return n;
85
+ }
86
+ /** 现在有几个在跑(诊断用)。 */
87
+ list() {
88
+ return [...this.jobs.entries()].map(([handle, j]) => ({
89
+ handle,
90
+ done: j.status.done,
91
+ startedAt: j.startedAt,
92
+ }));
93
+ }
94
+ }
95
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/seams/jobs/index.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@
14
14
  */
15
15
  import { type Context, Service } from '@deepseek-ai/cordis';
16
16
  import type { MediaAdapter } from '../../providers/media/adapters.js';
17
+ import type { MediaCapability } from '../../providers/media/mediaProviders.js';
17
18
  /** 插件页展示用。**由插件自己声明** —— 前端写死的表对第三方永远是空的。 */
18
19
  export declare const category = "\u5A92\u4F53";
19
20
  export declare const description = "\u5A92\u4F53\u9002\u914D\u5668\u6CE8\u518C\u8868 \u2014\u2014 \u751F\u56FE / \u751F\u89C6\u9891 / TTS \u5404\u5BB6\u5382\u5546\u7684\u8C03\u7528\u65B9\u5F0F\u3002";
@@ -24,6 +25,36 @@ export default class MediaAdapterRegistry extends Service {
24
25
  register(id: string, adapter: MediaAdapter): () => void;
25
26
  get(id: string): MediaAdapter | undefined;
26
27
  list(): string[];
28
+ /**
29
+ * 用注册进来的适配器**生成一个媒体资产**并落盘。
30
+ *
31
+ * 🔴 这是"注册表"之外唯一的一个使用方法,加它是有理由的:
32
+ * `generateAsset` 的第一个入参就是这张注册表,而它**完全与领域无关**
33
+ * (capability / prompt / size / outPath —— 没有一个游戏概念)。
34
+ * 插件要生图时,若够不着它就只有两条烂路:
35
+ * 进程内绕一圈 MCP 工具(那是给 agent 的形态),
36
+ * 或者在插件里把整套 provider 解析**重写一遍**。
37
+ *
38
+ * ⚠️ **它是同步等待的**(一张图几十秒)。async 能力应当把它丢进 `sps.jobs`,
39
+ * 而不是在 `start` 里 await —— 后者会把 tick 卡住。
40
+ */
41
+ generate(spec: {
42
+ capability: MediaCapability;
43
+ prompt: string;
44
+ /** 运行目录(产物落这)。 */
45
+ cwd: string;
46
+ /** 相对 cwd 的输出路径;省略则自动命名到 assets/。 */
47
+ outPath?: string;
48
+ size?: string;
49
+ referenceUrl?: string;
50
+ /** 点名用哪一家;不传 = 按能力解析默认那家。 */
51
+ providerId?: string;
52
+ }): Promise<{
53
+ path: string;
54
+ provider: string;
55
+ model?: string;
56
+ bytes: number;
57
+ }>;
27
58
  }
28
59
  declare module '@deepseek-ai/cordis' {
29
60
  interface Context {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/seams/media/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,KAAK,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AAEtE,6CAA6C;AAC7C,eAAO,MAAM,QAAQ,iBAAO,CAAC;AAC7B,eAAO,MAAM,WAAW,uKACiB,CAAC;AAG1C,eAAO,MAAM,KAAK,cAAc,CAAC;AAEjC,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,OAAO;IACvD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmC;gBAE5C,GAAG,EAAE,OAAO;IAIxB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,IAAI;IAQvD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIzC,IAAI,IAAI,MAAM,EAAE;CAGjB;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,WAAW,EAAE,oBAAoB,CAAC;KACnC;CACF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/seams/media/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,KAAK,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAE/E,6CAA6C;AAC7C,eAAO,MAAM,QAAQ,iBAAO,CAAC;AAC7B,eAAO,MAAM,WAAW,uKACiB,CAAC;AAG1C,eAAO,MAAM,KAAK,cAAc,CAAC;AAEjC,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,OAAO;IACvD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmC;gBAE5C,GAAG,EAAE,OAAO;IAIxB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,IAAI;IAQvD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIzC,IAAI,IAAI,MAAM,EAAE;IAIhB;;;;;;;;;;;;OAYG;IACG,QAAQ,CAAC,IAAI,EAAE;QACnB,UAAU,EAAE,eAAe,CAAC;QAC5B,MAAM,EAAE,MAAM,CAAC;QACf,kBAAkB;QAClB,GAAG,EAAE,MAAM,CAAC;QACZ,qCAAqC;QACrC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,6BAA6B;QAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAI/E;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,WAAW,EAAE,oBAAoB,CAAC;KACnC;CACF"}
@@ -37,5 +37,22 @@ export default class MediaAdapterRegistry extends Service {
37
37
  list() {
38
38
  return [...this.byId.keys()].sort();
39
39
  }
40
+ /**
41
+ * 用注册进来的适配器**生成一个媒体资产**并落盘。
42
+ *
43
+ * 🔴 这是"注册表"之外唯一的一个使用方法,加它是有理由的:
44
+ * `generateAsset` 的第一个入参就是这张注册表,而它**完全与领域无关**
45
+ * (capability / prompt / size / outPath —— 没有一个游戏概念)。
46
+ * 插件要生图时,若够不着它就只有两条烂路:
47
+ * 进程内绕一圈 MCP 工具(那是给 agent 的形态),
48
+ * 或者在插件里把整套 provider 解析**重写一遍**。
49
+ *
50
+ * ⚠️ **它是同步等待的**(一张图几十秒)。async 能力应当把它丢进 `sps.jobs`,
51
+ * 而不是在 `start` 里 await —— 后者会把 tick 卡住。
52
+ */
53
+ async generate(spec) {
54
+ const { generateAsset } = await import('../../providers/media/generateAsset.js');
55
+ return generateAsset({ adapters: this, ...spec });
56
+ }
40
57
  }
41
58
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/seams/media/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAgB,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAG5D,6CAA6C;AAC7C,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC;AAC7B,MAAM,CAAC,MAAM,WAAW,GACtB,uCAAuC,CAAC;AAG1C,MAAM,CAAC,MAAM,KAAK,GAAG,WAAW,CAAC;AAEjC,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,OAAO;IACtC,IAAI,GAAG,IAAI,GAAG,EAAwB,CAAC;IAExD,YAAY,GAAY;QACtB,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACpB,CAAC;IAED,QAAQ,CAAC,EAAU,EAAE,OAAqB;QACxC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC3B,OAAO,GAAG,EAAE;YACV,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,OAAO;gBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC1D,CAAC,CAAC;IACJ,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACtC,CAAC;CACF"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/seams/media/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAgB,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAI5D,6CAA6C;AAC7C,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC;AAC7B,MAAM,CAAC,MAAM,WAAW,GACtB,uCAAuC,CAAC;AAG1C,MAAM,CAAC,MAAM,KAAK,GAAG,WAAW,CAAC;AAEjC,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,OAAO;IACtC,IAAI,GAAG,IAAI,GAAG,EAAwB,CAAC;IAExD,YAAY,GAAY;QACtB,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACpB,CAAC;IAED,QAAQ,CAAC,EAAU,EAAE,OAAqB;QACxC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC3B,OAAO,GAAG,EAAE;YACV,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,OAAO;gBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC1D,CAAC,CAAC;IACJ,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACtC,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,QAAQ,CAAC,IAWd;QACC,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,wCAAwC,CAAC,CAAC;QACjF,OAAO,aAAa,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coralai/sps-cli",
3
- "version": "0.82.0",
3
+ "version": "0.83.0",
4
4
  "description": "SPS CLI — AI-driven development pipeline orchestrator",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",