c0de-agent 1.11.0 → 1.13.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/README.md +63 -16
- package/dist/cli/commands/acp.js +26 -8
- package/dist/cli/commands/chat.js +151 -1
- package/dist/cli/commands/config.d.ts +2 -0
- package/dist/cli/commands/config.js +63 -3
- package/dist/cli/commands/serve.js +11 -2
- package/dist/cli/commands/sessions.js +109 -3
- package/dist/cli/commands/trust.d.ts +11 -0
- package/dist/cli/commands/trust.js +31 -0
- package/dist/cli/commands/update.js +4 -0
- package/dist/cli/deps.d.ts +9 -6
- package/dist/cli/deps.js +66 -19
- package/dist/cli/index.d.ts +4 -1
- package/dist/cli/index.js +110 -11
- package/dist/cli/modes/acp.js +39 -8
- package/dist/cli/modes/print.d.ts +3 -0
- package/dist/cli/modes/print.js +78 -8
- package/dist/core/agent.d.ts +1 -1
- package/dist/core/agent.js +9 -4
- package/dist/core/agents/builtin.js +2 -2
- package/dist/core/agents/index.d.ts +0 -1
- package/dist/core/agents/index.js +0 -1
- package/dist/core/compact.d.ts +2 -0
- package/dist/core/compact.js +1 -0
- package/dist/core/config.d.ts +53 -2
- package/dist/core/config.js +235 -19
- package/dist/core/loop/compaction.d.ts +2 -1
- package/dist/core/loop/compaction.js +19 -6
- package/dist/core/loop/segment.d.ts +3 -1
- package/dist/core/loop/segment.js +24 -1
- package/dist/core/loop/stream-collect.js +9 -1
- package/dist/core/loop/subagent.js +88 -37
- package/dist/core/loop.d.ts +7 -0
- package/dist/core/loop.js +90 -6
- package/dist/core/redact.d.ts +11 -0
- package/dist/core/redact.js +49 -0
- package/dist/core/slash.d.ts +10 -0
- package/dist/core/slash.js +237 -65
- package/dist/core/title.js +7 -1
- package/dist/core/types.d.ts +22 -1
- package/dist/core/workflows/context.js +44 -4
- package/dist/core/workflows/discovery.d.ts +2 -2
- package/dist/core/workflows/discovery.js +5 -7
- package/dist/core/workflows/index.d.ts +2 -1
- package/dist/core/workflows/index.js +2 -1
- package/dist/core/workflows/registry.d.ts +13 -3
- package/dist/core/workflows/registry.js +14 -9
- package/dist/core/workflows/resolve.d.ts +22 -0
- package/dist/core/workflows/resolve.js +23 -0
- package/dist/core/workflows/runtime.d.ts +6 -1
- package/dist/core/workflows/runtime.js +19 -2
- package/dist/db/schema.d.ts +373 -1
- package/dist/db/schema.js +60 -4
- package/dist/kanban/index.d.ts +2 -1
- package/dist/kanban/index.js +1 -1
- package/dist/kanban/store.d.ts +87 -1
- package/dist/kanban/store.js +429 -22
- package/dist/llm/index.d.ts +1 -1
- package/dist/llm/index.js +1 -1
- package/dist/llm/provider.js +1 -1
- package/dist/llm/registry.d.ts +7 -1
- package/dist/llm/registry.js +7 -1
- package/dist/llm/retry.d.ts +5 -2
- package/dist/llm/retry.js +6 -5
- package/dist/llm/routing.d.ts +24 -1
- package/dist/llm/routing.js +29 -1
- package/dist/plugins/init.d.ts +7 -0
- package/dist/plugins/init.js +22 -1
- package/dist/plugins/loader.d.ts +7 -1
- package/dist/plugins/loader.js +12 -4
- package/dist/project/index.d.ts +1 -1
- package/dist/project/index.js +1 -1
- package/dist/project/project.d.ts +37 -0
- package/dist/project/project.js +142 -1
- package/dist/project/trust.d.ts +65 -0
- package/dist/project/trust.js +328 -0
- package/dist/server/agent-manager.d.ts +15 -2
- package/dist/server/agent-manager.js +18 -3
- package/dist/server/app.js +45 -30
- package/dist/server/auth-manager.d.ts +26 -9
- package/dist/server/auth-manager.js +78 -42
- package/dist/server/context.js +14 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/middleware/auth.d.ts +11 -1
- package/dist/server/middleware/auth.js +25 -3
- package/dist/server/permission/interactive.d.ts +11 -3
- package/dist/server/permission/interactive.js +23 -4
- package/dist/server/permission/store.d.ts +14 -2
- package/dist/server/permission/store.js +39 -3
- package/dist/server/registry-config.d.ts +14 -0
- package/dist/server/registry-config.js +44 -0
- package/dist/server/routes/auth.js +66 -10
- package/dist/server/routes/chat.d.ts +21 -0
- package/dist/server/routes/chat.js +685 -52
- package/dist/server/routes/commands.d.ts +4 -2
- package/dist/server/routes/commands.js +9 -4
- package/dist/server/routes/config.js +180 -23
- package/dist/server/routes/files.js +142 -28
- package/dist/server/routes/kanban.js +218 -26
- package/dist/server/routes/permissions.d.ts +0 -4
- package/dist/server/routes/permissions.js +140 -7
- package/dist/server/routes/project.js +132 -29
- package/dist/server/routes/provider.js +54 -3
- package/dist/server/routes/session.js +463 -23
- package/dist/server/routes/tool.js +24 -5
- package/dist/server/routes/update.d.ts +11 -5
- package/dist/server/routes/update.js +145 -29
- package/dist/server/routes/usage.d.ts +4 -0
- package/dist/server/routes/usage.js +133 -0
- package/dist/server/routes/workflows.js +476 -87
- package/dist/server/server.d.ts +16 -13
- package/dist/server/server.js +364 -107
- package/dist/server/terminal/pty-manager.d.ts +12 -0
- package/dist/server/terminal/pty-manager.js +63 -7
- package/dist/server/types.d.ts +16 -0
- package/dist/session/archive.d.ts +3 -1
- package/dist/session/archive.js +13 -1
- package/dist/session/branch.d.ts +2 -1
- package/dist/session/branch.js +92 -9
- package/dist/session/context.js +28 -2
- package/dist/session/import.d.ts +44 -0
- package/dist/session/import.js +83 -0
- package/dist/session/index.d.ts +1 -1
- package/dist/session/index.js +1 -1
- package/dist/session/jobs.d.ts +12 -0
- package/dist/session/jobs.js +53 -0
- package/dist/session/message.d.ts +7 -1
- package/dist/session/message.js +21 -1
- package/dist/session/session.d.ts +186 -12
- package/dist/session/session.js +577 -33
- package/dist/session/snapshot.d.ts +5 -2
- package/dist/session/snapshot.js +10 -2
- package/dist/session/types.d.ts +13 -1
- package/dist/session/usage.d.ts +62 -0
- package/dist/session/usage.js +194 -0
- package/dist/shared/types/agent.d.ts +29 -2
- package/dist/shared/types/config.d.ts +64 -5
- package/dist/shared/types/kanban.d.ts +17 -2
- package/dist/shared/types/message.d.ts +23 -0
- package/dist/tools/builtin/kanban.js +13 -2
- package/dist/tools/index.d.ts +14 -3
- package/dist/tools/index.js +23 -5
- package/dist/tools/websearch/index.d.ts +5 -1
- package/dist/tools/websearch/index.js +46 -7
- package/dist/tools/websearch/providers/brave.js +2 -2
- package/dist/tools/websearch/providers/duckduckgo.js +2 -1
- package/dist/tools/websearch/providers/tavily.js +2 -2
- package/dist/tools/websearch/types.d.ts +5 -1
- package/dist/tools/websearch/types.js +7 -1
- package/dist/update/index.d.ts +3 -3
- package/dist/update/index.js +2 -2
- package/dist/update/ipc.d.ts +13 -2
- package/dist/update/ipc.js +36 -2
- package/dist/update/scheduler.js +5 -2
- package/dist/update/snapshot.d.ts +18 -3
- package/dist/update/snapshot.js +5 -2
- package/dist/update/updater.d.ts +17 -1
- package/dist/update/updater.js +47 -18
- package/dist/update/version.d.ts +3 -0
- package/dist/update/version.js +9 -3
- package/drizzle/0008_tranquil_lily_hollister.sql +1 -0
- package/drizzle/0010_usage_events_ledger.sql +17 -0
- package/drizzle/0011_slow_slapstick.sql +12 -0
- package/drizzle/0012_chief_timeslip.sql +1 -0
- package/drizzle/0013_swift_zeigeist.sql +1 -0
- package/drizzle/0014_flimsy_legion.sql +1 -0
- package/drizzle/meta/0008_snapshot.json +875 -0
- package/drizzle/meta/0010_snapshot.json +1010 -0
- package/drizzle/meta/0011_snapshot.json +1055 -0
- package/drizzle/meta/0012_snapshot.json +1062 -0
- package/drizzle/meta/0013_snapshot.json +1068 -0
- package/drizzle/meta/0014_snapshot.json +1075 -0
- package/drizzle/meta/_journal.json +42 -0
- package/package.json +42 -42
- package/dist/core/agents/discovery.d.ts +0 -6
- package/dist/core/agents/discovery.js +0 -96
package/dist/db/schema.js
CHANGED
|
@@ -13,6 +13,14 @@ export const projects = pgTable('projects', {
|
|
|
13
13
|
gitRemote: text('git_remote'),
|
|
14
14
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
15
15
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
16
|
+
/** 用户显式信任该项目作用域配置/插件的时间;null=未信任。
|
|
17
|
+
* 信任是「克隆即信任」防线的落点:含风险配置(auto 权限/插件)的未信任项目
|
|
18
|
+
* 在聊天入口被门禁拦截,须显式确认。 */
|
|
19
|
+
trustedAt: timestamp('trusted_at', { withTimezone: true }).default(sql `null`),
|
|
20
|
+
/** 信任时项目作用域风险配置的指纹(sha256 over summarizeProjectRisk 输出)。
|
|
21
|
+
* 用于检测「信任后配置漂移」:仓库后续 git pull 新增 auto 权限/插件/MCP 等
|
|
22
|
+
* 风险键时,指纹变化 → 重新触发信任门禁,而非永久信任。null=历史记录/无指纹。 */
|
|
23
|
+
riskFingerprint: text('risk_fingerprint').default(sql `null`),
|
|
16
24
|
});
|
|
17
25
|
/**
|
|
18
26
|
* Sessions table — conversation sessions with branching support.
|
|
@@ -31,8 +39,10 @@ export const sessions = pgTable('sessions', {
|
|
|
31
39
|
worktreePath: text('worktree_path'),
|
|
32
40
|
/** 会话来源:'web'(Web UI)/ 'cli'(CLI print 模式);null=旧数据视为 web。 */
|
|
33
41
|
source: text('source').default(sql `null`),
|
|
34
|
-
/** 软删除时间戳;null=未删除。回收站保留
|
|
42
|
+
/** 软删除时间戳;null=未删除。回收站保留 60 天后物理清除。 */
|
|
35
43
|
deletedAt: timestamp('deleted_at', { withTimezone: true }).default(sql `null`),
|
|
44
|
+
/** 删除级联批次号:同一次 softDeleteSession 的父+后代共享;恢复时仅还原同批次后代。 */
|
|
45
|
+
deletedBatchId: uuid('deleted_batch_id'),
|
|
36
46
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
37
47
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
38
48
|
}, (table) => [
|
|
@@ -119,16 +129,26 @@ export const toolMetrics = pgTable('tool_metrics', {
|
|
|
119
129
|
/**
|
|
120
130
|
* Kanban boards — one per project (unique projectId). Stores column/label
|
|
121
131
|
* configuration as JSON; cards live in kanban_cards.
|
|
132
|
+
* P2-5:项目删除不再级联销毁看板——projectId 置 null + deletedAt 标记,
|
|
133
|
+
* 进入回收站「未归属看板」分组,60 天后随清理任务物理清除;恢复时可重新归属。
|
|
122
134
|
*/
|
|
123
135
|
export const kanbanBoards = pgTable('kanban_boards', {
|
|
124
136
|
id: uuid('id').primaryKey().defaultRandom(),
|
|
125
|
-
projectId: text('project_id')
|
|
126
|
-
.notNull()
|
|
127
|
-
.references(() => projects.id, { onDelete: 'cascade' }),
|
|
137
|
+
projectId: text('project_id').references(() => projects.id, { onDelete: 'set null' }),
|
|
128
138
|
/** Column definitions: [{ id, name }] */
|
|
129
139
|
columns: jsonb('columns').notNull(),
|
|
130
140
|
/** Label definitions: [{ id, name, color }] */
|
|
131
141
|
labels: jsonb('labels').notNull().default([]),
|
|
142
|
+
/** 软删除时间戳;null=活动看板。删除时记录原项目名供回收站展示。 */
|
|
143
|
+
deletedAt: timestamp('deleted_at', { withTimezone: true }).default(sql `null`),
|
|
144
|
+
deletedProjectName: text('deleted_project_name'),
|
|
145
|
+
/** 删除项目时记录的原项目工作目录;null 或目录已不存在时无法「重建原项目」恢复。
|
|
146
|
+
* 与 deletedProjectName(展示名)分离——name 可能为 null 或重名,路径才是重建依据。 */
|
|
147
|
+
deletedProjectWorktree: text('deleted_project_worktree'),
|
|
148
|
+
/** 回收站条目已到期、进入物理清除宽限期的时间戳(null=未到期)。
|
|
149
|
+
* 到期先标记,宽限期(默认 7 天)内 UI 仍可恢复;期满后由
|
|
150
|
+
* purgeDeletedKanbanBoards 物理清除——与会话回收站同策略,杜绝「到期即静默清空」。 */
|
|
151
|
+
purgePendingAt: timestamp('purge_pending_at', { withTimezone: true }).default(sql `null`),
|
|
132
152
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
133
153
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
134
154
|
}, (table) => [uniqueIndex('uq_kanban_boards_project').on(table.projectId)]);
|
|
@@ -152,3 +172,39 @@ export const kanbanCards = pgTable('kanban_cards', {
|
|
|
152
172
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
153
173
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
154
174
|
}, (table) => [index('idx_kanban_cards_board').on(table.boardId, table.columnId, table.position)]);
|
|
175
|
+
/**
|
|
176
|
+
* Usage events — append-only LLM cost ledger (P2 cost accounting decoupled from
|
|
177
|
+
* session lifecycle). One row per LLM call, written by loop manageSegment.
|
|
178
|
+
* No FK to sessions/projects: physical purge of sessions (recycle-bin expiry,
|
|
179
|
+
* manual forever-delete, temp CLI cleanup) must NOT erase spent-cost records —
|
|
180
|
+
* 成本是账本. sessionId/projectId are denormalized provenance only.
|
|
181
|
+
*/
|
|
182
|
+
export const usageEvents = pgTable('usage_events', {
|
|
183
|
+
id: uuid('id').primaryKey().defaultRandom(),
|
|
184
|
+
/** LLM 调用 id(segments 中 LLMCall.id)——唯一约束使 backfill 幂等。 */
|
|
185
|
+
callId: uuid('call_id').notNull(),
|
|
186
|
+
sessionId: uuid('session_id'),
|
|
187
|
+
projectId: text('project_id'),
|
|
188
|
+
provider: text('provider').notNull(),
|
|
189
|
+
model: text('model').notNull(),
|
|
190
|
+
inputTokens: bigint('input_tokens', { mode: 'number' }).notNull().default(0),
|
|
191
|
+
outputTokens: bigint('output_tokens', { mode: 'number' }).notNull().default(0),
|
|
192
|
+
cacheRead: bigint('cache_read', { mode: 'number' }).default(0),
|
|
193
|
+
/** null = 价格未知(按 $0 计入并由聚合层计数提示)。 */
|
|
194
|
+
cost: real('cost'),
|
|
195
|
+
/** LLM 请求发起时间(epoch ms)。 */
|
|
196
|
+
timestamp: bigint('timestamp', { mode: 'number' }).notNull(),
|
|
197
|
+
}, (table) => [
|
|
198
|
+
uniqueIndex('uq_usage_events_call').on(table.callId),
|
|
199
|
+
index('idx_usage_events_project_ts').on(table.projectId, table.timestamp),
|
|
200
|
+
index('idx_usage_events_ts').on(table.timestamp),
|
|
201
|
+
]);
|
|
202
|
+
/**
|
|
203
|
+
* App metadata — 一次性迁移/初始化标记(key-value)。
|
|
204
|
+
* P3-8:usage backfill 迁移完成后写 'usage_backfill_v1' 标记,
|
|
205
|
+
* 后续启动跳过全表扫描(导入/备份路径不依赖 backfill 的会话不再产生账本行)。
|
|
206
|
+
*/
|
|
207
|
+
export const appMeta = pgTable('app_meta', {
|
|
208
|
+
key: text('key').primaryKey(),
|
|
209
|
+
value: text('value').notNull(),
|
|
210
|
+
});
|
package/dist/kanban/index.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export type { DeletedKanbanBoard, KanbanTrashPurgeResult, MergeKanbanBoardResult, RestoreKanbanBoardResult, } from './store.js';
|
|
2
|
+
export { createKanbanStore, getDeletedKanbanBoard, KanbanCardNotFoundError, KanbanColumnInUseError, KanbanColumnNotFoundError, KanbanInvalidPriorityError, listDeletedKanbanBoards, mergeKanbanBoard, permanentlyDeleteKanbanBoard, purgeDeletedKanbanBoards, restoreKanbanBoard, softDeleteKanbanBoard, } from './store.js';
|
package/dist/kanban/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { createKanbanStore } from './store.js';
|
|
1
|
+
export { createKanbanStore, getDeletedKanbanBoard, KanbanCardNotFoundError, KanbanColumnInUseError, KanbanColumnNotFoundError, KanbanInvalidPriorityError, listDeletedKanbanBoards, mergeKanbanBoard, permanentlyDeleteKanbanBoard, purgeDeletedKanbanBoards, restoreKanbanBoard, softDeleteKanbanBoard, } from './store.js';
|
package/dist/kanban/store.d.ts
CHANGED
|
@@ -1,8 +1,94 @@
|
|
|
1
1
|
import type { DB } from '../db/client.js';
|
|
2
2
|
import type { KanbanStore } from '../shared/types/kanban.js';
|
|
3
|
+
/** 列内仍有卡片时禁止删除该列(否则卡片静默不可见)。 */
|
|
4
|
+
declare class KanbanColumnInUseError extends Error {
|
|
5
|
+
constructor(columnNames: string[], cardCount: number, cardIds?: string[]);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* 目标列不存在(add/move 引用未配置的列)——与 import/删列的悬空列防护同口径:
|
|
9
|
+
* 此前运行时 add/move 不校验,LLM 幻觉列名写入后卡片静默不可见,且幽灵卡片
|
|
10
|
+
* 会反过来冻结列配置删除(KanbanColumnInUseError 死锁)。
|
|
11
|
+
* 错误信息回传可用列清单,供 LLM 自纠而非再猜。
|
|
12
|
+
*/
|
|
13
|
+
declare class KanbanColumnNotFoundError extends Error {
|
|
14
|
+
readonly columnId: string;
|
|
15
|
+
constructor(columnId: string, availableColumns: string[], op: 'add' | 'move');
|
|
16
|
+
}
|
|
17
|
+
/** 非法优先级(REST PATCH / kanbanTool 透传未校验值)。 */
|
|
18
|
+
declare class KanbanInvalidPriorityError extends Error {
|
|
19
|
+
readonly value: string;
|
|
20
|
+
constructor(value: string);
|
|
21
|
+
}
|
|
22
|
+
/** 卡片不存在(update/move 目标 id 无效)。 */
|
|
23
|
+
declare class KanbanCardNotFoundError extends Error {
|
|
24
|
+
readonly cardId: string;
|
|
25
|
+
constructor(cardId: string);
|
|
26
|
+
}
|
|
3
27
|
/**
|
|
4
28
|
* Create a project-scoped KanbanStore backed by the given db handle.
|
|
5
29
|
* The board is created on first access (lazy) with the default 5 columns.
|
|
6
30
|
*/
|
|
7
31
|
declare function createKanbanStore(handle: DB, projectId: string): KanbanStore;
|
|
8
|
-
export { createKanbanStore };
|
|
32
|
+
export { createKanbanStore, KanbanCardNotFoundError, KanbanColumnInUseError, KanbanColumnNotFoundError, KanbanInvalidPriorityError, };
|
|
33
|
+
/** 回收站条目信息(列表展示用)。 */
|
|
34
|
+
export type DeletedKanbanBoard = {
|
|
35
|
+
id: string;
|
|
36
|
+
/** 删除时记录的原项目名(项目行已删除,无法再 join)。 */
|
|
37
|
+
projectName: string;
|
|
38
|
+
cardCount: number;
|
|
39
|
+
deletedAt: number;
|
|
40
|
+
/** 已到期进入物理清除宽限期的时间戳(ms);null=尚未到期。 */
|
|
41
|
+
purgePendingAt: number | null;
|
|
42
|
+
/** 删除时记录的原项目工作目录;null 或目录已不存在时无法「重建原项目」恢复。 */
|
|
43
|
+
deletedProjectWorktree: string | null;
|
|
44
|
+
};
|
|
45
|
+
/** 把活动看板软删除进回收站(记录原项目名与工作目录)。项目行删除后 FK 将 projectId 置 null。 */
|
|
46
|
+
export declare function softDeleteKanbanBoard(handle: DB, projectId: string, projectName: string | null, worktree?: string | null): Promise<boolean>;
|
|
47
|
+
/** 回收站看板列表(含卡片数)。 */
|
|
48
|
+
export declare function listDeletedKanbanBoards(handle: DB): Promise<DeletedKanbanBoard[]>;
|
|
49
|
+
/** 按 id 取单个回收站看板(供「重建原项目」恢复读取原工作目录)。 */
|
|
50
|
+
export declare function getDeletedKanbanBoard(handle: DB, boardId: string): Promise<DeletedKanbanBoard | null>;
|
|
51
|
+
export type RestoreKanbanBoardResult = {
|
|
52
|
+
ok: true;
|
|
53
|
+
} | {
|
|
54
|
+
ok: false;
|
|
55
|
+
reason: 'BOARD_NOT_FOUND' | 'TARGET_HAS_BOARD';
|
|
56
|
+
};
|
|
57
|
+
/** 恢复看板到指定项目:目标项目已有活动看板 → 409 语义(不覆盖用户现有看板)。
|
|
58
|
+
* P2 修复:检查与更新放进单事务,并发下撞 uq_kanban_boards_project 唯一索引时
|
|
59
|
+
* 降级为 TARGET_HAS_BOARD(此前抛 PG 错误 500)。 */
|
|
60
|
+
export declare function restoreKanbanBoard(handle: DB, boardId: string, projectId: string): Promise<RestoreKanbanBoardResult>;
|
|
61
|
+
export type MergeKanbanBoardResult = {
|
|
62
|
+
ok: true;
|
|
63
|
+
mergedColumns: number;
|
|
64
|
+
mergedCards: number;
|
|
65
|
+
} | {
|
|
66
|
+
ok: false;
|
|
67
|
+
reason: 'BOARD_NOT_FOUND';
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* P1 修复:把回收站看板合并进目标项目的活动看板(TARGET_HAS_BOARD 死胡同的出口)。
|
|
71
|
+
* 此前「目标项目已有看板」时恢复 409,而产品没有删除活动看板的能力,用户无法
|
|
72
|
+
* 把旧项目卡片拿回现有项目——现在 merge 模式下:
|
|
73
|
+
* - 目标无活动看板 → 等价普通恢复(重新归属);
|
|
74
|
+
* - 目标有活动看板 → 追加缺失列,卡片并入对应列末尾(position 重新计算避免
|
|
75
|
+
* 与目标卡片重叠);源卡片引用源板已不存在列时落到目标第一列(保证可见);
|
|
76
|
+
* - 合并成功后源看板物理删除(卡片已迁移,FK cascade 清源卡)。
|
|
77
|
+
* 全程单事务:失败整体回滚,不残留半合并状态。
|
|
78
|
+
*/
|
|
79
|
+
export declare function mergeKanbanBoard(handle: DB, boardId: string, projectId: string): Promise<MergeKanbanBoardResult>;
|
|
80
|
+
/** 回收站内彻底删除看板(不可恢复)。 */
|
|
81
|
+
export declare function permanentlyDeleteKanbanBoard(handle: DB, boardId: string): Promise<number>;
|
|
82
|
+
/** 两阶段清理结果:marked = 本次新标记进入宽限期的条目数;deleted = 本次物理清除数。 */
|
|
83
|
+
export type KanbanTrashPurgeResult = {
|
|
84
|
+
marked: number;
|
|
85
|
+
deleted: number;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* 看板回收站两阶段清理(与会话 purgeDeletedSessions 同策略,杜绝「到期即静默清空」):
|
|
89
|
+
* - 阶段一:软删除超过 retentionMs 且尚未标记 → 写 purgePendingAt(进入宽限期,
|
|
90
|
+
* UI 显示「即将清除」仍可恢复);
|
|
91
|
+
* - 阶段二:purgePendingAt 早于 graceMs 截止 → 物理清除(卡片经 FK cascade 连带删除)。
|
|
92
|
+
* 看板回收站全局单一分组、无「首次查看才起算」语义,保留期自删除时刻起算,稳定可预期。
|
|
93
|
+
*/
|
|
94
|
+
export declare function purgeDeletedKanbanBoards(handle: DB, retentionMs: number, graceMs: number): Promise<KanbanTrashPurgeResult>;
|