@coralai/sps-plugin-api 0.5.1 → 0.7.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.
Files changed (2) hide show
  1. package/dist/index.d.ts +135 -0
  2. package/package.json +1 -1
package/dist/index.d.ts CHANGED
@@ -94,6 +94,134 @@ export interface SpsPromptSection {
94
94
  export interface SpsSystemPrompt {
95
95
  section(section: SpsPromptSection): () => void;
96
96
  }
97
+ /**
98
+ * 一个**工具卡能力** —— 由编排驱动、不占 worker 槽位的那类执行体。
99
+ *
100
+ * 🔴 和 `sps.tools`(MCP 工具)的区别不是形状,是**谁触发、多久**:
101
+ * MCP 工具是 **agent 主动调**,agent 阻塞等它 —— 适合秒级。
102
+ * 能力是**编排调度的一张卡**,和 worker 并行、可以跑分钟级,
103
+ * `mode:'async'` 的甚至返回后任务仍在跑(由 join 卡等终态)。
104
+ * 要做"生成一批图"这种事,选能力,别选工具。
105
+ */
106
+ export type SpsAsyncPoll = {
107
+ done: false;
108
+ } | {
109
+ done: true;
110
+ ok: true;
111
+ result: Record<string, unknown>;
112
+ } | {
113
+ done: true;
114
+ ok: false;
115
+ error: string;
116
+ };
117
+ /** 两种能力共有的那部分。 */
118
+ export interface SpsCapabilityBase {
119
+ /** 能力 id,卡片用它引用。命名 `<域>.<动作>`,如 `art.chromaKey`。 */
120
+ id: string;
121
+ mode: 'sync' | 'async';
122
+ /**
123
+ * 参数形状由**能力**定,不是卡片里的自由 JSON。
124
+ * ⚠️ 运行时必须是一个 **Zod schema**(能力表拿它校验卡片参数)——
125
+ * 这里只声明结构最小面,免得契约包为此依赖 zod。
126
+ */
127
+ inputSchema: {
128
+ parse(value: unknown): unknown;
129
+ };
130
+ /**
131
+ * 这个能力会写什么(相对项目根的路径模式)。
132
+ * 🔴 **可审计性的来源**:不读代码就知道这张卡会写什么。
133
+ * ⚠️ 你声明了不等于 sps 会拦 —— 越界靠围栏兜(realpath + 项目根内),不靠这条声明。
134
+ */
135
+ produces: string[];
136
+ /** 可信度来源。卡片不看这一格,**审计要看**。 */
137
+ source: {
138
+ kind: 'built-in';
139
+ } | {
140
+ kind: 'script';
141
+ template: string;
142
+ script: string;
143
+ };
144
+ /** 一句话说明,给编排页展示。 */
145
+ summary: string;
146
+ /**
147
+ * 这个能力失败时,**这张卡怎么处置**。缺省 `'block'`。
148
+ * ```
149
+ * block 留在原地打 NEEDS-FIX —— 波次屏障挡住后面所有卡,图上看得见它卡住了
150
+ * skip 标 Canceled ⇒ 屏障**放行**,后续卡照跑(留痕写进卡片 meta)
151
+ * ```
152
+ * 🔴 声明式,不是"能力自己去改卡片状态" —— 后者会让卡片有两个写入方。
153
+ * ⚠️ `'skip'` 给"部分失败是常态"的工序用;scaffold/package 这种别用。
154
+ */
155
+ onFailure?: 'block' | 'skip';
156
+ }
157
+ export interface SpsCapabilityCtx {
158
+ /** 项目在共享树下的相对路径(`t<租户>/<产品>/<项目>`)。 */
159
+ project: string;
160
+ /** 项目工作区绝对路径。**能力不从卡片收路径**,只从这里取根。 */
161
+ projectDir: string;
162
+ }
163
+ /** 同步能力:`run` 返回即完成。 */
164
+ export interface SpsSyncCapability extends SpsCapabilityBase {
165
+ mode: 'sync';
166
+ run(input: unknown, ctx: SpsCapabilityCtx): Promise<Record<string, unknown>>;
167
+ }
168
+ /**
169
+ * 异步能力:`start` 立刻返回,引擎每个 tick `poll` 一次。
170
+ *
171
+ * 🔴 **卡片在真正跑完之前不标 Done** —— 波次屏障(`order`)因此天然成为 join。
172
+ * "打包必须等美术"用 order 表达即可,没有单独的 join 卡执行路径,也不需要。
173
+ */
174
+ export interface SpsAsyncCapability extends SpsCapabilityBase {
175
+ mode: 'async';
176
+ /** 启动外部任务并**立刻返回**。handle 存进卡片 meta。 */
177
+ start(input: unknown, ctx: SpsCapabilityCtx): Promise<{
178
+ handle: string;
179
+ }>;
180
+ /**
181
+ * 问状态。**每个 tick 都会调 ⇒ 必须便宜且幂等。**
182
+ * 别在这里重新扫盘或重新请求全量 —— 它会按 tick 频率被放大。
183
+ */
184
+ poll(handle: string, ctx: SpsCapabilityCtx): Promise<SpsAsyncPoll>;
185
+ /**
186
+ * 多久算超时(ms)。缺省 **30 分钟**。
187
+ * ⚠️ 超时**由引擎按 startedAt 判**,不问你 —— 你可能正好卡死在自己的等待上。
188
+ */
189
+ timeoutMs?: number;
190
+ }
191
+ export type SpsCapability = SpsSyncCapability | SpsAsyncCapability;
192
+ export interface SpsCapabilities {
193
+ register(cap: SpsCapability): () => void;
194
+ get(id: string): SpsCapability | undefined;
195
+ list(): SpsCapability[];
196
+ }
197
+ /**
198
+ * ⚠️ 下面四个的**载荷形状**(adapter / factory)住在 sps 里,还没有真实的第三方消费方,
199
+ * 所以这里只声明**注册表本身**,载荷留 `unknown`。
200
+ * 要写这四类插件时告诉我们,按真实需求把形状定出来 ——
201
+ * 凭空定一个大接口,大概率定错位置和粒度。
202
+ */
203
+ export interface SpsRegistryByKey<T = unknown> {
204
+ register(key: string, value: T): () => void;
205
+ get(key: string): T | undefined;
206
+ list(): string[];
207
+ }
208
+ /** 工厂自带 id,注册时不另给 key。 */
209
+ export interface SpsRegistryByFactory<T = unknown> {
210
+ register(factory: T): () => void;
211
+ list(): string[];
212
+ }
213
+ /**
214
+ * ⚠️ 同上:这两个是**甲·工厂型**(换实现,不是收一组),
215
+ * 今天没有第三方在换它们。声明方法名,形状留 `unknown`。
216
+ */
217
+ export interface SpsMemory {
218
+ buildInjection(refs: unknown[]): string;
219
+ }
220
+ export interface SpsNotifier {
221
+ open(config: unknown): {
222
+ send(message: string, level?: 'info' | 'success' | 'warning' | 'error'): Promise<void>;
223
+ };
224
+ }
97
225
  /** 建一张卡。形状照 MCP 面上的 `add_card`,不另发明。 */
98
226
  export interface SpsNewCard {
99
227
  title: string;
@@ -318,6 +446,13 @@ export interface SpsPluginContext {
318
446
  'sps.events': SpsEvents;
319
447
  'sps.projects': SpsProjects;
320
448
  'sps.cards': SpsCards;
449
+ 'sps.capabilities': SpsCapabilities;
450
+ 'sps.media': SpsRegistryByKey;
451
+ 'sps.im': SpsRegistryByKey;
452
+ 'sps.agents': SpsRegistryByFactory;
453
+ 'sps.repo': SpsRegistryByFactory;
454
+ 'sps.memory': SpsMemory;
455
+ 'sps.notifier': SpsNotifier;
321
456
  'sps.subprocess': SpsSubprocess;
322
457
  'sps.attachments': SpsAttachments;
323
458
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coralai/sps-plugin-api",
3
- "version": "0.5.1",
3
+ "version": "0.7.0",
4
4
  "description": "sps 宿主半区的插件契约:ctx 上那些服务的方法签名。插件装它拿类型。",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",