@capybara-hq/kernel 0.1.0-rc.3 → 0.1.0-rc.4
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/dist/admin/admin.controller.d.ts +9 -4
- package/dist/admin/admin.controller.js +13 -4
- package/dist/admin/extensions.controller.d.ts +8 -1
- package/dist/admin/extensions.controller.js +22 -2
- package/dist/agents/agent-lookup.d.ts +3 -0
- package/dist/agents/agent-lookup.js +10 -0
- package/dist/agents/agent-profile.service.d.ts +29 -0
- package/dist/agents/agent-profile.service.js +117 -0
- package/dist/agents/agents.controller.d.ts +93 -3
- package/dist/agents/agents.controller.js +114 -4
- package/dist/agents/agents.module.js +6 -2
- package/dist/agents/agents.service.d.ts +13 -5
- package/dist/agents/agents.service.js +30 -7
- package/dist/agents/definition.d.ts +4 -0
- package/dist/agents/definition.js +10 -0
- package/dist/agents/instruction-files.d.ts +60 -0
- package/dist/agents/instruction-files.js +111 -0
- package/dist/agents/models.controller.d.ts +9 -3
- package/dist/agents/models.controller.js +19 -4
- package/dist/agents/profile.d.ts +96 -0
- package/dist/agents/profile.js +51 -0
- package/dist/agents/readiness.controller.d.ts +26 -0
- package/dist/agents/readiness.controller.js +56 -0
- package/dist/agents/templates.js +1 -1
- package/dist/background/background.controller.d.ts +38 -0
- package/dist/background/background.controller.js +87 -0
- package/dist/background/background.module.d.ts +10 -0
- package/dist/background/background.module.js +32 -0
- package/dist/background/finish.d.ts +43 -0
- package/dist/background/finish.js +94 -0
- package/dist/background/launch-lock.d.ts +14 -0
- package/dist/background/launch-lock.js +39 -0
- package/dist/background/launch.d.ts +36 -0
- package/dist/background/launch.js +70 -0
- package/dist/background/poll.job.d.ts +53 -0
- package/dist/background/poll.job.js +182 -0
- package/dist/background/render.d.ts +23 -0
- package/dist/background/render.js +48 -0
- package/dist/background/session.d.ts +37 -0
- package/dist/background/session.js +66 -0
- package/dist/background/status.d.ts +35 -0
- package/dist/background/status.js +57 -0
- package/dist/background/stop.d.ts +62 -0
- package/dist/background/stop.js +225 -0
- package/dist/background/store.d.ts +150 -0
- package/dist/background/store.js +351 -0
- package/dist/background/store.module.d.ts +6 -0
- package/dist/background/store.module.js +22 -0
- package/dist/background/tasks.service.d.ts +67 -0
- package/dist/background/tasks.service.js +186 -0
- package/dist/background/wake-rules.d.ts +57 -0
- package/dist/background/wake-rules.js +83 -0
- package/dist/background/wake.d.ts +28 -0
- package/dist/background/wake.js +57 -0
- package/dist/catalog/claude/agents.js +2 -0
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/plugin-import.js +1 -1
- package/dist/catalog/plugin-upgrade.js +1 -1
- package/dist/channels/cards.js +1 -1
- package/dist/channels/connections.service.d.ts +16 -1
- package/dist/channels/connections.service.js +38 -4
- package/dist/channels/threads.d.ts +5 -0
- package/dist/channels/threads.js +8 -0
- package/dist/config/schema.d.ts +18 -0
- package/dist/config/schema.js +102 -0
- package/dist/conversations/access.js +2 -0
- package/dist/conversations/attachments.service.d.ts +30 -0
- package/dist/conversations/attachments.service.js +130 -5
- package/dist/conversations/conversations.controller.d.ts +36 -5
- package/dist/conversations/conversations.controller.js +62 -12
- package/dist/conversations/conversations.module.js +3 -0
- package/dist/conversations/conversations.service.d.ts +44 -2
- package/dist/conversations/conversations.service.js +140 -12
- package/dist/conversations/event-log.d.ts +1 -1
- package/dist/conversations/event-log.js +10 -1
- package/dist/conversations/events.d.ts +58 -0
- package/dist/conversations/events.js +57 -2
- package/dist/conversations/queue.d.ts +3 -1
- package/dist/conversations/queue.js +13 -2
- package/dist/conversations/queue.service.js +3 -1
- package/dist/conversations/titles.d.ts +7 -0
- package/dist/conversations/titles.js +15 -0
- package/dist/db/kernel-schema.d.ts +58 -2
- package/dist/db/pool.d.ts +5 -0
- package/dist/db/pool.js +3 -0
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +8 -0
- package/dist/evals/run-replay.d.ts +5 -2
- package/dist/evals/run-replay.js +30 -7
- package/dist/evals/step-replay.js +12 -6
- package/dist/evals/trajectory.js +1 -1
- package/dist/extensions/admin-ops.js +2 -0
- package/dist/extensions/admin-view.d.ts +3 -1
- package/dist/extensions/admin-view.js +10 -2
- package/dist/extensions/blobs.js +1 -0
- package/dist/extensions/config-issues.d.ts +13 -1
- package/dist/extensions/config-issues.js +22 -5
- package/dist/extensions/config-json-schema.d.ts +43 -7
- package/dist/extensions/config-json-schema.js +124 -58
- package/dist/extensions/deployment-config-store.d.ts +6 -0
- package/dist/extensions/deployment-config.d.ts +50 -3
- package/dist/extensions/deployment-config.js +125 -28
- package/dist/extensions/display-name.d.ts +22 -0
- package/dist/extensions/display-name.js +77 -0
- package/dist/extensions/extensions.module.js +6 -0
- package/dist/extensions/host.d.ts +26 -1
- package/dist/extensions/host.js +82 -9
- package/dist/extensions/org-config.controller.d.ts +11 -3
- package/dist/extensions/org-config.controller.js +14 -6
- package/dist/extensions/org-config.d.ts +6 -0
- package/dist/extensions/org-config.js +12 -13
- package/dist/extensions/package.d.ts +14 -1
- package/dist/extensions/package.js +51 -2
- package/dist/extensions/permission-view.d.ts +3 -0
- package/dist/extensions/point-defaults.controller.d.ts +34 -0
- package/dist/extensions/point-defaults.controller.js +71 -0
- package/dist/extensions/point-defaults.d.ts +64 -0
- package/dist/extensions/point-defaults.js +206 -0
- package/dist/extensions/registry.d.ts +1 -1
- package/dist/extensions/registry.js +2 -0
- package/dist/http/api.module.js +8 -0
- package/dist/http/nest-logger.d.ts +6 -5
- package/dist/http/nest-logger.js +24 -10
- package/dist/identity/auth.controller.js +9 -5
- package/dist/identity/cookies.d.ts +20 -5
- package/dist/identity/cookies.js +44 -6
- package/dist/identity/me.controller.d.ts +5 -1
- package/dist/identity/me.controller.js +12 -3
- package/dist/identity/sessions.d.ts +12 -0
- package/dist/identity/sessions.js +45 -0
- package/dist/index.d.ts +1 -1
- package/dist/infra/config/kernel-config.service.js +6 -0
- package/dist/infra/database/database.module.js +1 -0
- package/dist/infra/events/kernel-events.d.ts +8 -0
- package/dist/infra/lifecycle/process-guards.js +4 -0
- package/dist/infra/logging/logging.module.d.ts +4 -2
- package/dist/infra/logging/logging.module.js +24 -6
- package/dist/infra/queue/redis-connection.d.ts +6 -0
- package/dist/infra/queue/redis-connection.js +7 -0
- package/dist/infra/redis/redis.module.js +6 -2
- package/dist/infra/tokens.d.ts +6 -1
- package/dist/infra/tokens.js +6 -1
- package/dist/log.d.ts +13 -1
- package/dist/log.js +93 -17
- package/dist/models/purposes.d.ts +23 -0
- package/dist/models/purposes.js +31 -10
- package/dist/orgs/offboarding.d.ts +3 -1
- package/dist/orgs/offboarding.js +26 -16
- package/dist/orgs/settings.service.d.ts +5 -0
- package/dist/orgs/settings.service.js +13 -2
- package/dist/roles/worker.module.js +6 -0
- package/dist/runtime/context/build.d.ts +9 -7
- package/dist/runtime/context/build.js +27 -19
- package/dist/runtime/context/claude-tools.d.ts +2 -1
- package/dist/runtime/context/claude-tools.js +5 -4
- package/dist/runtime/context/compaction.js +4 -0
- package/dist/runtime/langgraph-loop.js +3 -2
- package/dist/runtime/loop.d.ts +4 -3
- package/dist/runtime/maintenance.d.ts +4 -2
- package/dist/runtime/maintenance.js +17 -5
- package/dist/runtime/model-call.d.ts +17 -1
- package/dist/runtime/model-call.js +3 -2
- package/dist/runtime/providers.d.ts +6 -0
- package/dist/runtime/providers.js +8 -0
- package/dist/runtime/run-queue.d.ts +25 -2
- package/dist/runtime/run-queue.js +129 -33
- package/dist/runtime/run-worker.js +16 -3
- package/dist/runtime/runtime.module.js +8 -3
- package/dist/runtime/step-log.d.ts +6 -0
- package/dist/runtime/step-log.js +16 -2
- package/dist/runtime/subagents/definition.js +3 -1
- package/dist/runtime/usage-report.d.ts +2 -1
- package/dist/runtime/usage-report.js +2 -1
- package/dist/runtime/waits.d.ts +8 -2
- package/dist/runtime/waits.js +37 -11
- package/dist/sandbox/sandbox.module.js +6 -1
- package/dist/sandbox/sandbox.service.d.ts +61 -3
- package/dist/sandbox/sandbox.service.js +141 -7
- package/dist/tools/approvals.service.js +2 -0
- package/dist/tools/builtin-names.d.ts +20 -2
- package/dist/tools/builtin-names.js +29 -2
- package/dist/tools/builtins/builtin-tools.d.ts +15 -1
- package/dist/tools/builtins/builtin-tools.js +34 -2
- package/dist/tools/builtins/sandbox/bash.d.ts +1 -1
- package/dist/tools/builtins/sandbox/bash.js +230 -3
- package/dist/tools/builtins/sandbox/common.d.ts +27 -4
- package/dist/tools/builtins/sandbox/common.js +7 -3
- package/dist/tools/builtins/sandbox/deliver.js +1 -1
- package/dist/tools/builtins/sandbox/index.d.ts +2 -0
- package/dist/tools/builtins/sandbox/index.js +6 -0
- package/dist/tools/builtins/sandbox/task-output.d.ts +63 -0
- package/dist/tools/builtins/sandbox/task-output.js +304 -0
- package/dist/tools/builtins/sandbox/task-stop.d.ts +10 -0
- package/dist/tools/builtins/sandbox/task-stop.js +112 -0
- package/dist/tools/builtins/web/errors.d.ts +8 -0
- package/dist/tools/builtins/web/errors.js +53 -0
- package/dist/tools/builtins/web/extract.d.ts +62 -0
- package/dist/tools/builtins/web/extract.js +267 -0
- package/dist/tools/builtins/web/fetch.d.ts +55 -0
- package/dist/tools/builtins/web/fetch.js +174 -0
- package/dist/tools/builtins/web/index.d.ts +13 -0
- package/dist/tools/builtins/web/index.js +12 -0
- package/dist/tools/builtins/web/page-cache.d.ts +25 -0
- package/dist/tools/builtins/web/page-cache.js +77 -0
- package/dist/tools/builtins/web/search.d.ts +25 -0
- package/dist/tools/builtins/web/search.js +209 -0
- package/dist/tools/builtins/web/url.d.ts +17 -0
- package/dist/tools/builtins/web/url.js +43 -0
- package/dist/tools/oauth/flow-paths.d.ts +1 -1
- package/dist/tools/oauth/flow-paths.js +1 -1
- package/dist/tools/pipeline.js +15 -0
- package/dist/tools/registry.d.ts +22 -3
- package/dist/tools/registry.js +26 -11
- package/dist/tools/tools.module.js +12 -0
- package/dist/tools/validate.js +1 -1
- package/package.json +3 -3
- package/src/migrations/0064_account_last_org.sql +7 -0
- package/src/migrations/0065_conversation_archive.sql +8 -0
- package/src/migrations/0066_extension_display_name.sql +4 -0
- package/src/migrations/0067_agent_profiles.sql +20 -0
- package/src/migrations/0068_agent_avatar_uploads.sql +7 -0
- package/src/migrations/0069_attachments_agent_idx.sql +3 -0
- package/src/migrations/0070_background_tasks.sql +37 -0
- package/src/migrations/0071_background_tasks_reserve.sql +6 -0
- package/src/migrations/0072_background_tasks_stopping.sql +5 -0
- package/src/migrations/0073_org_extension_point_defaults.sql +11 -0
|
@@ -40,6 +40,16 @@ export const MAX_PENDING_SKILL_PACKAGES = 5;
|
|
|
40
40
|
* `POST /skills` 开始处理时再顺延这么久,处理期间不会被清理。
|
|
41
41
|
*/
|
|
42
42
|
export const SKILL_PACKAGE_TTL_HOURS = 1;
|
|
43
|
+
/** The image types an agent avatar upload may have (cropped square in the browser). */
|
|
44
|
+
export const AGENT_AVATAR_CONTENT_TYPES = ["image/png", "image/jpeg", "image/webp"];
|
|
45
|
+
/** The size limit of an agent avatar upload (bytes). */
|
|
46
|
+
export const AGENT_AVATAR_MAX_BYTES = 2 * 1024 * 1024;
|
|
47
|
+
/** Unfinished avatar uploads one account may have in an org (counted apart from other uploads). */
|
|
48
|
+
export const MAX_PENDING_AGENT_AVATARS = 10;
|
|
49
|
+
/** An avatar upload not saved into a profile expires (and is cleaned up) after this many hours. */
|
|
50
|
+
export const AGENT_AVATAR_TTL_HOURS = 24;
|
|
51
|
+
/** Download redirect lifetime of an avatar (seconds); also its `Cache-Control` max-age. */
|
|
52
|
+
export const AGENT_AVATAR_DOWNLOAD_TTL_SECONDS = 300;
|
|
43
53
|
/**
|
|
44
54
|
* 技能包解出的文件在 `kernel/<orgId>/` 下的前缀:按上传 id,同一上传重试写到同一批键(幂等),
|
|
45
55
|
* 并发处理同一上传也不会互相覆盖出不同内容。版本行记下这个前缀(`skill_versions.object_prefix`)。
|
|
@@ -56,7 +66,11 @@ const notFound = () => new ApiError("attachment.not_found", "Attachment not foun
|
|
|
56
66
|
export const normalizeContentType = (ct) => (ct.split(";")[0] ?? "").trim().toLowerCase();
|
|
57
67
|
const isImage = (ct) => IMAGE_MEDIA_TYPES.includes(ct);
|
|
58
68
|
/** 对象键:只用附件 id,用户的文件名不进键。技能包另放 `skill-packages/<id>`。 */
|
|
59
|
-
const objectKey = (id, purpose = "chat") => purpose === "chat"
|
|
69
|
+
const objectKey = (id, purpose = "chat") => purpose === "chat"
|
|
70
|
+
? `attachments/${id}`
|
|
71
|
+
: purpose === "agent-avatar"
|
|
72
|
+
? `agent-avatars/${id}`
|
|
73
|
+
: `skill-packages/${id}`;
|
|
60
74
|
const startsWith = (b, sig, at = 0) => sig.every((x, i) => b[at + i] === x);
|
|
61
75
|
const ascii = (s) => [...s].map((c) => c.charCodeAt(0));
|
|
62
76
|
/** 文件开头是否与声明的类型相符(图片与 PDF 看签名,文本不能含 NUL)。 */
|
|
@@ -139,12 +153,19 @@ let AttachmentsService = class AttachmentsService {
|
|
|
139
153
|
const cfg = this.config.get().attachments;
|
|
140
154
|
const contentType = normalizeContentType(input.contentType);
|
|
141
155
|
const skill = purpose === "skill-package";
|
|
156
|
+
const avatar = purpose === "agent-avatar";
|
|
142
157
|
if (skill
|
|
143
158
|
? contentType !== SKILL_PACKAGE_CONTENT_TYPE
|
|
144
|
-
:
|
|
159
|
+
: avatar
|
|
160
|
+
? !AGENT_AVATAR_CONTENT_TYPES.includes(contentType)
|
|
161
|
+
: !cfg.allowedTypes.includes(contentType)) {
|
|
145
162
|
throw new ApiError("attachment.type_not_allowed", `Attachment type ${JSON.stringify(contentType)} is not allowed`);
|
|
146
163
|
}
|
|
147
|
-
const limit = skill
|
|
164
|
+
const limit = skill
|
|
165
|
+
? SKILL_PACKAGE_UPLOAD_MAX_BYTES
|
|
166
|
+
: avatar
|
|
167
|
+
? AGENT_AVATAR_MAX_BYTES
|
|
168
|
+
: this.limitFor(contentType);
|
|
148
169
|
if (input.size > limit) {
|
|
149
170
|
throw new ApiError("attachment.too_large", `Attachment is ${input.size} bytes, over the limit of ${limit} bytes`);
|
|
150
171
|
}
|
|
@@ -156,13 +177,21 @@ let AttachmentsService = class AttachmentsService {
|
|
|
156
177
|
.where("status", "=", "pending")
|
|
157
178
|
.where("purpose", "=", purpose)
|
|
158
179
|
.executeTakeFirst();
|
|
159
|
-
const maxPending = skill
|
|
180
|
+
const maxPending = skill
|
|
181
|
+
? MAX_PENDING_SKILL_PACKAGES
|
|
182
|
+
: avatar
|
|
183
|
+
? MAX_PENDING_AGENT_AVATARS
|
|
184
|
+
: MAX_PENDING_ATTACHMENTS;
|
|
160
185
|
if (Number(pending?.n ?? 0) >= maxPending) {
|
|
161
186
|
throw new ApiError("attachment.too_many_pending", `Too many unfinished uploads (at most ${maxPending}); finish or wait for them first`);
|
|
162
187
|
}
|
|
163
188
|
const id = randomUUID();
|
|
164
189
|
const key = objectKey(id, purpose);
|
|
165
|
-
const ttlHours = skill
|
|
190
|
+
const ttlHours = skill
|
|
191
|
+
? SKILL_PACKAGE_TTL_HOURS
|
|
192
|
+
: avatar
|
|
193
|
+
? AGENT_AVATAR_TTL_HOURS
|
|
194
|
+
: cfg.unboundTtlHours;
|
|
166
195
|
const upload = await this.storage.kernel(orgId).presignPut(key, {
|
|
167
196
|
contentType,
|
|
168
197
|
maxSize: input.size,
|
|
@@ -541,6 +570,99 @@ let AttachmentsService = class AttachmentsService {
|
|
|
541
570
|
.where("id", "=", id)
|
|
542
571
|
.execute();
|
|
543
572
|
}
|
|
573
|
+
/**
|
|
574
|
+
* Makes an agent avatar upload ready to be saved into a profile (outside any transaction: it may
|
|
575
|
+
* read the object store): only the uploader, only the `agent-avatar` purpose, an image type, not
|
|
576
|
+
* expired and not yet used by another agent, else `attachment.not_found`. An upload still
|
|
577
|
+
* `pending` is finalized first (size, type and the image signature are checked). The expiry is
|
|
578
|
+
* extended so the cleanup job cannot delete it before {@link consumeAgentAvatar} runs.
|
|
579
|
+
*/
|
|
580
|
+
async prepareAgentAvatar(orgId, accountId, id, agentId) {
|
|
581
|
+
this.storage.assertAvailable();
|
|
582
|
+
const row = await this.db
|
|
583
|
+
.selectFrom("attachments")
|
|
584
|
+
.select([
|
|
585
|
+
"status",
|
|
586
|
+
"purpose",
|
|
587
|
+
"content_type",
|
|
588
|
+
"agent_id",
|
|
589
|
+
sql `expires_at is not null and expires_at <= now()`.as("expired"),
|
|
590
|
+
])
|
|
591
|
+
.where("id", "=", id)
|
|
592
|
+
.where("org_id", "=", orgId)
|
|
593
|
+
.where("account_id", "=", accountId)
|
|
594
|
+
.executeTakeFirst();
|
|
595
|
+
if (row?.purpose !== "agent-avatar" ||
|
|
596
|
+
row.status === "deleting" ||
|
|
597
|
+
row.expired ||
|
|
598
|
+
(row.agent_id !== null && row.agent_id !== agentId) ||
|
|
599
|
+
!AGENT_AVATAR_CONTENT_TYPES.includes(row.content_type)) {
|
|
600
|
+
throw notFound();
|
|
601
|
+
}
|
|
602
|
+
if (row.status === "pending")
|
|
603
|
+
await this.finalize(orgId, accountId, id);
|
|
604
|
+
await this.db
|
|
605
|
+
.updateTable("attachments")
|
|
606
|
+
.set({ expires_at: sql `now() + make_interval(hours => ${AGENT_AVATAR_TTL_HOURS})` })
|
|
607
|
+
.where("id", "=", id)
|
|
608
|
+
.where("status", "=", "ready")
|
|
609
|
+
.where("agent_id", "is", null)
|
|
610
|
+
.where("expires_at", "is not", null)
|
|
611
|
+
.execute();
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* In the caller's transaction, binds a ready avatar upload to `agentId` (row lock; the expiry is
|
|
615
|
+
* cleared, so the cleanup job keeps it while the profile uses it). An upload another agent
|
|
616
|
+
* already uses, or one that is not the account's ready avatar → `attachment.not_found`; saving
|
|
617
|
+
* the same upload to the same agent again is fine.
|
|
618
|
+
*/
|
|
619
|
+
async consumeAgentAvatar(orgId, accountId, id, agentId) {
|
|
620
|
+
const trx = this.db.db;
|
|
621
|
+
const row = await trx
|
|
622
|
+
.selectFrom("attachments")
|
|
623
|
+
.select(["status", "agent_id"])
|
|
624
|
+
.where("id", "=", id)
|
|
625
|
+
.where("org_id", "=", orgId)
|
|
626
|
+
.where("account_id", "=", accountId)
|
|
627
|
+
.where("purpose", "=", "agent-avatar")
|
|
628
|
+
.forUpdate()
|
|
629
|
+
.executeTakeFirst();
|
|
630
|
+
if (row?.status !== "ready" || (row.agent_id !== null && row.agent_id !== agentId)) {
|
|
631
|
+
throw notFound();
|
|
632
|
+
}
|
|
633
|
+
await trx
|
|
634
|
+
.updateTable("attachments")
|
|
635
|
+
.set({ agent_id: agentId, expires_at: null })
|
|
636
|
+
.where("id", "=", id)
|
|
637
|
+
.execute();
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* A short-lived presigned GET (inline, with the checked image type) of the avatar upload bound
|
|
641
|
+
* to `agentId`; `null` when there is none or its object is gone or no longer the finalized one.
|
|
642
|
+
*/
|
|
643
|
+
async agentAvatarUrl(orgId, agentId, id) {
|
|
644
|
+
this.storage.assertAvailable();
|
|
645
|
+
const row = await this.db
|
|
646
|
+
.selectFrom("attachments")
|
|
647
|
+
.select(["content_type", "object_key", "etag"])
|
|
648
|
+
.where("id", "=", id)
|
|
649
|
+
.where("org_id", "=", orgId)
|
|
650
|
+
.where("agent_id", "=", agentId)
|
|
651
|
+
.where("purpose", "=", "agent-avatar")
|
|
652
|
+
.where("status", "=", "ready")
|
|
653
|
+
.executeTakeFirst();
|
|
654
|
+
if (!row)
|
|
655
|
+
return null;
|
|
656
|
+
const store = this.storage.kernel(orgId);
|
|
657
|
+
const head = await store.head(row.object_key);
|
|
658
|
+
if (!head || !this.sameContent(row.etag, head.etag, { orgId, attachmentId: id }))
|
|
659
|
+
return null;
|
|
660
|
+
return store.presignGet(row.object_key, {
|
|
661
|
+
ttlSeconds: AGENT_AVATAR_DOWNLOAD_TTL_SECONDS,
|
|
662
|
+
disposition: "inline",
|
|
663
|
+
responseContentType: row.content_type,
|
|
664
|
+
});
|
|
665
|
+
}
|
|
544
666
|
/**
|
|
545
667
|
* 删除过期(`expires_at < now()`)且从未绑定到会话的附件:先把行认领为 `deleting`(`FOR UPDATE SKIP LOCKED`,
|
|
546
668
|
* 多副本并发时互不重复),再删对象、删行。删对象失败的行保持 `deleting`,下次运行重试。
|
|
@@ -613,6 +735,9 @@ __decorate([
|
|
|
613
735
|
__decorate([
|
|
614
736
|
Transactional({ propagation: "mandatory" })
|
|
615
737
|
], AttachmentsService.prototype, "consumeSkillPackage", null);
|
|
738
|
+
__decorate([
|
|
739
|
+
Transactional({ propagation: "mandatory" })
|
|
740
|
+
], AttachmentsService.prototype, "consumeAgentAvatar", null);
|
|
616
741
|
AttachmentsService = __decorate([
|
|
617
742
|
Injectable(),
|
|
618
743
|
__param(0, Inject(KernelDb)),
|
|
@@ -12,11 +12,27 @@ import type { QueueItem, QueuePauseReason } from "./queue.js";
|
|
|
12
12
|
import { ConversationQueue } from "./queue.service.js";
|
|
13
13
|
import { ConversationSandboxStatus, type SandboxStatusView } from "./sandbox-status.js";
|
|
14
14
|
declare const ListQuery: z.ZodObject<{
|
|
15
|
+
q: z.ZodOptional<z.ZodString>;
|
|
16
|
+
state: z.ZodOptional<z.ZodEnum<{
|
|
17
|
+
running: "running";
|
|
18
|
+
waiting: "waiting";
|
|
19
|
+
}>>;
|
|
20
|
+
archived: z.ZodOptional<z.ZodEnum<{
|
|
21
|
+
1: "1";
|
|
22
|
+
}>>;
|
|
15
23
|
after: z.ZodOptional<z.ZodString>;
|
|
16
24
|
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
17
25
|
agentId: z.ZodOptional<z.ZodString>;
|
|
18
26
|
}, z.core.$strip>;
|
|
19
27
|
declare const GroupsQuery: z.ZodObject<{
|
|
28
|
+
q: z.ZodOptional<z.ZodString>;
|
|
29
|
+
state: z.ZodOptional<z.ZodEnum<{
|
|
30
|
+
running: "running";
|
|
31
|
+
waiting: "waiting";
|
|
32
|
+
}>>;
|
|
33
|
+
archived: z.ZodOptional<z.ZodEnum<{
|
|
34
|
+
1: "1";
|
|
35
|
+
}>>;
|
|
20
36
|
perGroup: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
21
37
|
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
22
38
|
after: z.ZodOptional<z.ZodString>;
|
|
@@ -142,9 +158,13 @@ declare const QueueEditBody: z.ZodObject<{
|
|
|
142
158
|
* A rename: 1–120 characters counted in code points after trimming, with no control or format
|
|
143
159
|
* (bidi, zero-width) characters, the same rule generated and tool titles follow.
|
|
144
160
|
*/
|
|
145
|
-
declare const
|
|
146
|
-
title: z.ZodString
|
|
161
|
+
declare const PatchBody: z.ZodObject<{
|
|
162
|
+
title: z.ZodOptional<z.ZodString>;
|
|
163
|
+
archived: z.ZodOptional<z.ZodBoolean>;
|
|
147
164
|
}, z.core.$strict>;
|
|
165
|
+
declare const IdParams: z.ZodObject<{
|
|
166
|
+
id: z.ZodString;
|
|
167
|
+
}, z.core.$strip>;
|
|
148
168
|
/**
|
|
149
169
|
* 会话(`/api/v1/orgs/:orgId/conversations`):`agents.use`(访客以上),只接受人类用户;
|
|
150
170
|
* 服务令牌 → 403 `forbidden`。只有会话所有者可见,其他人一律 `conversation.not_found`。
|
|
@@ -158,15 +178,25 @@ export declare class ConversationsController {
|
|
|
158
178
|
private readonly queue;
|
|
159
179
|
private readonly files;
|
|
160
180
|
constructor(conversations: ConversationsService, outputs: ConversationOutputs, artifacts: ConversationArtifacts, sandboxStatus: ConversationSandboxStatus, toolInfo: ConversationToolInfo, queue: ConversationQueue, files: ConversationFiles);
|
|
161
|
-
/**
|
|
181
|
+
/**
|
|
182
|
+
* 201 when created; 200 when `message.clientMessageId` repeats an earlier first send. With a
|
|
183
|
+
* message the answer has `event` (the `user_message`) and `events`: every event the first send
|
|
184
|
+
* wrote, in seq order from seq 1 (a `model_switched` first when it switched).
|
|
185
|
+
*/
|
|
162
186
|
create(principal: Principal, org: OrgContext, body: z.infer<typeof CreateBody>, reply: FastifyReply): Promise<{
|
|
163
187
|
conversation: ConversationView;
|
|
164
188
|
event?: ConversationEvent;
|
|
189
|
+
events?: ConversationEvent[];
|
|
165
190
|
}>;
|
|
166
|
-
/**
|
|
167
|
-
|
|
191
|
+
/**
|
|
192
|
+
* Rename and / or archive (owner only). A rename makes `titleSource` `manual`, so the title is
|
|
193
|
+
* never regenerated; `archived` archives or unarchives. Returns the final view.
|
|
194
|
+
*/
|
|
195
|
+
patch(principal: Principal, org: OrgContext, id: string, body: z.infer<typeof PatchBody>): Promise<{
|
|
168
196
|
conversation: ConversationView;
|
|
169
197
|
}>;
|
|
198
|
+
/** Soft delete (owner only): stops an active run and hides the conversation everywhere. */
|
|
199
|
+
remove(principal: Principal, org: OrgContext, { id }: z.infer<typeof IdParams>): Promise<void>;
|
|
170
200
|
/** 我的会话,最近更新的在前:`next` 为下一页游标(作为 `after` 传回),没有更多时为 null。 */
|
|
171
201
|
list(principal: Principal, org: OrgContext, q: z.infer<typeof ListQuery>): Promise<{
|
|
172
202
|
conversations: ConversationView[];
|
|
@@ -180,6 +210,7 @@ export declare class ConversationsController {
|
|
|
180
210
|
groups(principal: Principal, org: OrgContext, q: z.infer<typeof GroupsQuery>): Promise<{
|
|
181
211
|
groups: ConversationGroup[];
|
|
182
212
|
next: string | null;
|
|
213
|
+
archivedCount: number;
|
|
183
214
|
}>;
|
|
184
215
|
get(principal: Principal, org: OrgContext, id: string): Promise<{
|
|
185
216
|
conversation: ConversationView;
|
|
@@ -12,7 +12,7 @@ import { z } from "zod";
|
|
|
12
12
|
import { ModelRef } from "../agents/definition.js";
|
|
13
13
|
import { CurrentPrincipal, requireUser } from "../identity/principal.js";
|
|
14
14
|
import { createZodDto } from "../infra/validation/create-zod-dto.js";
|
|
15
|
-
import { ZBody, ZQuery } from "../infra/validation/zod-params.js";
|
|
15
|
+
import { ZBody, ZParam, ZQuery } from "../infra/validation/zod-params.js";
|
|
16
16
|
import { CurrentOrg, OrgAction } from "../orgs/org.guard.js";
|
|
17
17
|
import { CONTROL_OR_HIDDEN_RE } from "../text.js";
|
|
18
18
|
import { MAX_ATTACHMENTS } from "../tools/connector-content.js";
|
|
@@ -23,17 +23,25 @@ import { ConversationFiles, FILE_CONTENT_MAX_BYTES, FILES_PAGE_MAX, } from "./fi
|
|
|
23
23
|
import { ConversationOutputs, OUTPUT_PAGE_MAX_CHARS } from "./outputs-read.js";
|
|
24
24
|
import { ConversationQueue } from "./queue.service.js";
|
|
25
25
|
import { ConversationSandboxStatus } from "./sandbox-status.js";
|
|
26
|
+
/** Shared by the list and groups queries: title search, run activity and the archived list. */
|
|
27
|
+
const searchFields = {
|
|
28
|
+
q: z.string().min(1).max(100).optional(),
|
|
29
|
+
state: z.enum(["running", "waiting"]).optional(),
|
|
30
|
+
archived: z.enum(["1"]).optional(),
|
|
31
|
+
};
|
|
26
32
|
const ListQuery = z.object({
|
|
27
33
|
after: z.string().min(1).max(100).optional(),
|
|
28
34
|
limit: z.coerce.number().int().min(1).max(200).default(50),
|
|
29
35
|
/** Only this agent's conversations (the sidebar's per-group "More"). */
|
|
30
36
|
agentId: z.string().min(1).max(100).optional(),
|
|
37
|
+
...searchFields,
|
|
31
38
|
});
|
|
32
39
|
const GroupsQuery = z.object({
|
|
33
40
|
perGroup: z.coerce.number().int().min(1).max(20).default(5),
|
|
34
41
|
limit: z.coerce.number().int().min(1).max(50).default(20),
|
|
35
42
|
/** The last group's agent id from the previous page (`next`). */
|
|
36
43
|
after: z.string().min(1).max(100).optional(),
|
|
44
|
+
...searchFields,
|
|
37
45
|
});
|
|
38
46
|
const SubagentsQuery = z.object({
|
|
39
47
|
/** The previous page's last sub-agent id (`next`). */
|
|
@@ -143,7 +151,7 @@ const QueueEditBody = z.object({ text: z.string().max(100_000) }).strict();
|
|
|
143
151
|
* A rename: 1–120 characters counted in code points after trimming, with no control or format
|
|
144
152
|
* (bidi, zero-width) characters, the same rule generated and tool titles follow.
|
|
145
153
|
*/
|
|
146
|
-
const
|
|
154
|
+
const PatchBody = z
|
|
147
155
|
.object({
|
|
148
156
|
title: z
|
|
149
157
|
.string()
|
|
@@ -151,12 +159,19 @@ const RenameBody = z
|
|
|
151
159
|
.trim()
|
|
152
160
|
.refine((t) => t.length > 0, "title must not be empty")
|
|
153
161
|
.refine((t) => Array.from(t).length <= CONVERSATION_TITLE_MAX_CHARS, `title must be at most ${CONVERSATION_TITLE_MAX_CHARS} characters`)
|
|
154
|
-
.refine((t) => !CONTROL_OR_HIDDEN_RE.test(t), "title must not contain control or format characters")
|
|
162
|
+
.refine((t) => !CONTROL_OR_HIDDEN_RE.test(t), "title must not contain control or format characters")
|
|
163
|
+
.optional(),
|
|
164
|
+
/** true archives (hidden from the default lists), false unarchives. */
|
|
165
|
+
archived: z.boolean().optional(),
|
|
155
166
|
})
|
|
156
|
-
.strict()
|
|
167
|
+
.strict()
|
|
168
|
+
.refine((b) => b.title !== undefined || b.archived !== undefined, "title or archived is required");
|
|
169
|
+
const IdParams = z.object({ id: z.string().min(1).max(100) });
|
|
157
170
|
class ConversationCreateBodyDto extends createZodDto(CreateBody, "ConversationCreateBody") {
|
|
158
171
|
}
|
|
159
|
-
class
|
|
172
|
+
class ConversationPatchBodyDto extends createZodDto(PatchBody, "ConversationPatchBody") {
|
|
173
|
+
}
|
|
174
|
+
class ConversationIdParamsDto extends createZodDto(IdParams, "ConversationIdParams") {
|
|
160
175
|
}
|
|
161
176
|
class ConversationListQueryDto extends createZodDto(ListQuery, "ConversationListQuery") {
|
|
162
177
|
}
|
|
@@ -203,7 +218,11 @@ let ConversationsController = class ConversationsController {
|
|
|
203
218
|
this.queue = queue;
|
|
204
219
|
this.files = files;
|
|
205
220
|
}
|
|
206
|
-
/**
|
|
221
|
+
/**
|
|
222
|
+
* 201 when created; 200 when `message.clientMessageId` repeats an earlier first send. With a
|
|
223
|
+
* message the answer has `event` (the `user_message`) and `events`: every event the first send
|
|
224
|
+
* wrote, in seq order from seq 1 (a `model_switched` first when it switched).
|
|
225
|
+
*/
|
|
207
226
|
async create(principal, org, body, reply) {
|
|
208
227
|
const p = requireUser(principal);
|
|
209
228
|
if (body.message === undefined) {
|
|
@@ -222,15 +241,32 @@ let ConversationsController = class ConversationsController {
|
|
|
222
241
|
...(m.skill !== undefined && { skill: m.skill }),
|
|
223
242
|
});
|
|
224
243
|
reply.status(out.created ? 201 : 200);
|
|
225
|
-
return { conversation: out.conversation, event: out.event };
|
|
244
|
+
return { conversation: out.conversation, event: out.event, events: out.events };
|
|
226
245
|
}
|
|
227
|
-
/**
|
|
228
|
-
|
|
246
|
+
/**
|
|
247
|
+
* Rename and / or archive (owner only). A rename makes `titleSource` `manual`, so the title is
|
|
248
|
+
* never regenerated; `archived` archives or unarchives. Returns the final view.
|
|
249
|
+
*/
|
|
250
|
+
async patch(principal, org, id, body) {
|
|
229
251
|
const p = requireUser(principal);
|
|
252
|
+
const renamed = body.title === undefined
|
|
253
|
+
? undefined
|
|
254
|
+
: await this.conversations.rename(org.orgId, id, p.account.id, body.title);
|
|
255
|
+
if (body.archived === undefined) {
|
|
256
|
+
// The refine guarantees a title when there is no `archived`
|
|
257
|
+
return {
|
|
258
|
+
conversation: renamed ?? (await this.conversations.get(org.orgId, id, p.account.id)),
|
|
259
|
+
};
|
|
260
|
+
}
|
|
230
261
|
return {
|
|
231
|
-
conversation: await this.conversations.
|
|
262
|
+
conversation: await this.conversations.setArchived(org.orgId, id, p.account.id, body.archived),
|
|
232
263
|
};
|
|
233
264
|
}
|
|
265
|
+
/** Soft delete (owner only): stops an active run and hides the conversation everywhere. */
|
|
266
|
+
async remove(principal, org, { id }) {
|
|
267
|
+
const p = requireUser(principal);
|
|
268
|
+
await this.conversations.remove(org.orgId, id, p.account.id);
|
|
269
|
+
}
|
|
234
270
|
/** 我的会话,最近更新的在前:`next` 为下一页游标(作为 `after` 传回),没有更多时为 null。 */
|
|
235
271
|
async list(principal, org, q) {
|
|
236
272
|
const p = requireUser(principal);
|
|
@@ -238,6 +274,9 @@ let ConversationsController = class ConversationsController {
|
|
|
238
274
|
limit: q.limit + 1,
|
|
239
275
|
...(q.after !== undefined && { after: q.after }),
|
|
240
276
|
...(q.agentId !== undefined && { agentId: q.agentId }),
|
|
277
|
+
...(q.q !== undefined && { q: q.q }),
|
|
278
|
+
...(q.state !== undefined && { state: q.state }),
|
|
279
|
+
...(q.archived !== undefined && { archived: true }),
|
|
241
280
|
});
|
|
242
281
|
const conversations = rows.slice(0, q.limit);
|
|
243
282
|
const next = rows.length > q.limit ? (conversations.at(-1)?.id ?? null) : null;
|
|
@@ -254,6 +293,9 @@ let ConversationsController = class ConversationsController {
|
|
|
254
293
|
perGroup: q.perGroup,
|
|
255
294
|
limit: q.limit,
|
|
256
295
|
...(q.after !== undefined && { after: q.after }),
|
|
296
|
+
...(q.q !== undefined && { q: q.q }),
|
|
297
|
+
...(q.state !== undefined && { state: q.state }),
|
|
298
|
+
...(q.archived !== undefined && { archived: true }),
|
|
257
299
|
});
|
|
258
300
|
}
|
|
259
301
|
async get(principal, org, id) {
|
|
@@ -443,8 +485,16 @@ __decorate([
|
|
|
443
485
|
__param(0, CurrentPrincipal()),
|
|
444
486
|
__param(1, CurrentOrg()),
|
|
445
487
|
__param(2, Param("id")),
|
|
446
|
-
__param(3, ZBody(
|
|
447
|
-
], ConversationsController.prototype, "
|
|
488
|
+
__param(3, ZBody(ConversationPatchBodyDto))
|
|
489
|
+
], ConversationsController.prototype, "patch", null);
|
|
490
|
+
__decorate([
|
|
491
|
+
Delete(":id"),
|
|
492
|
+
HttpCode(204),
|
|
493
|
+
OrgAction("agents.use"),
|
|
494
|
+
__param(0, CurrentPrincipal()),
|
|
495
|
+
__param(1, CurrentOrg()),
|
|
496
|
+
__param(2, ZParam(ConversationIdParamsDto))
|
|
497
|
+
], ConversationsController.prototype, "remove", null);
|
|
448
498
|
__decorate([
|
|
449
499
|
Get(),
|
|
450
500
|
OrgAction("agents.use"),
|
|
@@ -6,6 +6,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
6
6
|
};
|
|
7
7
|
import { Module } from "@nestjs/common";
|
|
8
8
|
import { AgentLookupModule } from "../agents/agent-lookup.js";
|
|
9
|
+
import { BackgroundModule } from "../background/background.module.js";
|
|
9
10
|
import { ProvidersModule } from "../runtime/providers.js";
|
|
10
11
|
import { RuntimeModule } from "../runtime/runtime.module.js";
|
|
11
12
|
import { SandboxModule } from "../sandbox/sandbox.module.js";
|
|
@@ -44,6 +45,8 @@ ConversationsModule = __decorate([
|
|
|
44
45
|
ProvidersModule,
|
|
45
46
|
// the sandbox status
|
|
46
47
|
SandboxModule,
|
|
48
|
+
// the stop of a deleted conversation's background tasks
|
|
49
|
+
BackgroundModule,
|
|
47
50
|
],
|
|
48
51
|
providers: [
|
|
49
52
|
ConversationsService,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AgentLookup } from "../agents/agent-lookup.js";
|
|
2
2
|
import type { ModelRef } from "../agents/definition.js";
|
|
3
|
+
import { BackgroundTaskStopper } from "../background/stop.js";
|
|
3
4
|
import type { TitleSource } from "../db/kernel-schema.js";
|
|
4
5
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
5
6
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
@@ -31,7 +32,16 @@ export interface ConversationView {
|
|
|
31
32
|
parentConversationId: string | null;
|
|
32
33
|
/** A sub-agent's type as resolved at its first dispatch; null for any other conversation. */
|
|
33
34
|
subagentType: string | null;
|
|
35
|
+
/** When the owner archived it; null = not archived (hidden from the default lists). */
|
|
36
|
+
archivedAt: Date | null;
|
|
37
|
+
/**
|
|
38
|
+
* What the latest run is doing: `running` (queued or running), `waiting` (an approval or a
|
|
39
|
+
* question), else null. Only the list queries compute it; other responses carry null.
|
|
40
|
+
*/
|
|
41
|
+
activity: "running" | "waiting" | null;
|
|
34
42
|
}
|
|
43
|
+
/** Escapes `\`, `%` and `_` so user text is matched literally by `LIKE … ESCAPE '\'`. */
|
|
44
|
+
export declare function escapeLike(s: string): string;
|
|
35
45
|
/** One agent's group in the sidebar list: the caller's newest conversations with that agent. */
|
|
36
46
|
export interface ConversationGroup {
|
|
37
47
|
agent: {
|
|
@@ -150,6 +160,8 @@ export declare class ConversationsService {
|
|
|
150
160
|
private readonly attachments;
|
|
151
161
|
/** Renders a person's skill invocation (phase D). */
|
|
152
162
|
private readonly invoker;
|
|
163
|
+
/** Stops a deleted conversation's background tasks. */
|
|
164
|
+
private readonly background;
|
|
153
165
|
readonly txHost: TransactionHost;
|
|
154
166
|
constructor(db: KernelDb, eventLog: EventLog, agents: Pick<AgentLookup, "get">, access: Pick<ConversationAccess, "isAccessible">,
|
|
155
167
|
/** Starts and stops the conversation's runs. */
|
|
@@ -161,7 +173,9 @@ export declare class ConversationsService {
|
|
|
161
173
|
/** Binds uploaded files to the conversation in the message's transaction. */
|
|
162
174
|
attachments: Pick<AttachmentsService, "bindForMessage">,
|
|
163
175
|
/** Renders a person's skill invocation (phase D). */
|
|
164
|
-
invoker: Pick<SkillInvoker, "prepare">,
|
|
176
|
+
invoker: Pick<SkillInvoker, "prepare">,
|
|
177
|
+
/** Stops a deleted conversation's background tasks. */
|
|
178
|
+
background: Pick<BackgroundTaskStopper, "stopForDeletedConversation">, txHost: TransactionHost);
|
|
165
179
|
/**
|
|
166
180
|
* 不阻塞地调用一次 `ensureRun`(打开 SSE、读事件时):它幂等,并顺带清理孤儿运行,
|
|
167
181
|
* 会话不会因为某次运行结束后的投递失败而永远停在「运行中」。失败只记日志。
|
|
@@ -175,12 +189,15 @@ export declare class ConversationsService {
|
|
|
175
189
|
* message's `clientMessageId` (`create_request_id`), so a retried send returns the same
|
|
176
190
|
* conversation and event with `created: false`. An agent the caller cannot use →
|
|
177
191
|
* `agent.not_found` and nothing is written. Queues a run afterwards, like `postUserMessage`.
|
|
192
|
+
* `events` are every event the create wrote, in seq order from seq 1 (a `model_switched` before
|
|
193
|
+
* the message when the send switched), so a client can seed the new conversation's log whole.
|
|
178
194
|
*/
|
|
179
195
|
createWithMessage(orgId: string, accountId: string, agentId: string, input: UserMessageInput & {
|
|
180
196
|
clientMessageId: string;
|
|
181
197
|
}): Promise<{
|
|
182
198
|
conversation: ConversationView;
|
|
183
199
|
event: ConversationEvent;
|
|
200
|
+
events: ConversationEvent[];
|
|
184
201
|
created: boolean;
|
|
185
202
|
}>;
|
|
186
203
|
/** The conversation row and its first message (undefined: a concurrent retry committed first). */
|
|
@@ -197,6 +214,23 @@ export declare class ConversationsService {
|
|
|
197
214
|
* job never overwrites it. Publishes `changed: title`. `title` is already trimmed and checked.
|
|
198
215
|
*/
|
|
199
216
|
rename(orgId: string, conversationId: string, accountId: string, title: string): Promise<ConversationView>;
|
|
217
|
+
/**
|
|
218
|
+
* Archives or unarchives a conversation (owner only, as {@link rename}). An archived
|
|
219
|
+
* conversation leaves the default lists but stays readable. Publishes `changed: archived`.
|
|
220
|
+
*/
|
|
221
|
+
setArchived(orgId: string, conversationId: string, accountId: string, archived: boolean): Promise<ConversationView>;
|
|
222
|
+
/**
|
|
223
|
+
* Soft-deletes a conversation (owner only; a sub-agent's conversation is `conversation.read_only`):
|
|
224
|
+
* stops an active run, hides the conversation everywhere for its owner and drops its channel
|
|
225
|
+
* bindings, then stops every running background task in its sandbox (its sub-agents' too;
|
|
226
|
+
* outside the delete's transaction, a task whose sandbox cannot be reached ends `lost` with
|
|
227
|
+
* `kill_pending`). The tasks are stopped after the conversation is marked deleted, so no finish
|
|
228
|
+
* (the stops' own, or one the poller writes meanwhile) can wake a run on it: `ensureRun` refuses a
|
|
229
|
+
* deleted conversation (the stops' finishes carry `stoppedBy: "deletion"` as well). The event
|
|
230
|
+
* log, runs and trajectory stay (enterprise admins still see them).
|
|
231
|
+
*/
|
|
232
|
+
remove(orgId: string, conversationId: string, accountId: string): Promise<void>;
|
|
233
|
+
private markDeleted;
|
|
200
234
|
/** 读会话:非所有者、或 agent 已对所有者不可用 → `conversation.not_found`。 */
|
|
201
235
|
get(orgId: string, conversationId: string, viewerAccountId: string): Promise<ConversationView>;
|
|
202
236
|
/**
|
|
@@ -216,6 +250,9 @@ export declare class ConversationsService {
|
|
|
216
250
|
after?: string;
|
|
217
251
|
limit: number;
|
|
218
252
|
agentId?: string;
|
|
253
|
+
archived?: boolean;
|
|
254
|
+
q?: string;
|
|
255
|
+
state?: "running" | "waiting";
|
|
219
256
|
}): Promise<ConversationView[]>;
|
|
220
257
|
/**
|
|
221
258
|
* My chat conversations grouped by agent (the sidebar, UI refresh spec §5.9), in one statement.
|
|
@@ -228,9 +265,13 @@ export declare class ConversationsService {
|
|
|
228
265
|
perGroup: number;
|
|
229
266
|
limit: number;
|
|
230
267
|
after?: string;
|
|
268
|
+
archived?: boolean;
|
|
269
|
+
q?: string;
|
|
270
|
+
state?: "running" | "waiting";
|
|
231
271
|
}): Promise<{
|
|
232
272
|
groups: ConversationGroup[];
|
|
233
273
|
next: string | null;
|
|
274
|
+
archivedCount: number;
|
|
234
275
|
}>;
|
|
235
276
|
/**
|
|
236
277
|
* The sub-agents of a conversation, newest first (sub-agents spec §14.3); owner only, as
|
|
@@ -292,7 +333,8 @@ export declare class ConversationsService {
|
|
|
292
333
|
checkPick(orgId: string, conv: ConversationView, accountId: string, pick: Pick<UserMessageInput, "model" | "effort">): Promise<void>;
|
|
293
334
|
/**
|
|
294
335
|
* Writes the message (preceded by its `model_switched` when it switches) inside `t` and updates
|
|
295
|
-
* `conversations.selection`; returns the
|
|
336
|
+
* `conversations.selection`; returns the events written, in seq order (the `user_message`
|
|
337
|
+
* last). The caller notifies after commit.
|
|
296
338
|
*/
|
|
297
339
|
private writeMessage;
|
|
298
340
|
/**
|