@nekro-nxt/contracts 0.2.0 → 0.3.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/src/host-api.ts CHANGED
@@ -33,6 +33,8 @@ import { ConfigSchemaDocumentSchema } from './config-schema.js'
33
33
  import {
34
34
  CommunityExtensionDetailSchema,
35
35
  CommunityExtensionSummarySchema,
36
+ CommunityExtensionSortSchema,
37
+ CommunityListingInputSchema,
36
38
  CommunityReleaseIdSchema,
37
39
  CommunityReviewStatusSchema,
38
40
  CommunityStatusSchema,
@@ -42,6 +44,16 @@ import {
42
44
  CommunityMyExtensionSchema,
43
45
  CommunityReviewReportSchema,
44
46
  } from './community.js'
47
+ import {
48
+ COMMUNITY_PERSONA_AVATAR_TYPES,
49
+ COMMUNITY_PERSONA_MAX_LENGTH,
50
+ CommunityMyPersonaSchema,
51
+ CommunityMyPersonasSchema,
52
+ CommunityPersonaDetailSchema,
53
+ CommunityPersonaIdSchema,
54
+ CommunityPersonaRevisionIdSchema,
55
+ CommunityPersonaSummarySchema,
56
+ } from './community-personas.js'
45
57
  import {
46
58
  DshNxtHostUiSchema,
47
59
  EMPTY_EXTENSION_UI_CONTRIBUTIONS,
@@ -54,6 +66,9 @@ import {
54
66
  HostUiPageGeometryEvidenceSchema,
55
67
  HostUiPageEntrySchema,
56
68
  HostUiPermissionDeclarationSchema,
69
+ ExtensionPanelAnchorSchema,
70
+ ExtensionPermissionsSchema,
71
+ ExtensionProvideSchema,
57
72
  } from './extension-ui.js'
58
73
 
59
74
  const EmptyParamsSchema = z.object({}).strict()
@@ -214,6 +229,32 @@ const AgentModelSchema = z
214
229
  })
215
230
  .strict()
216
231
 
232
+ /**
233
+ * An enable or disable request of one agent extension that has not settled: `waiting` until the agent reaches a safe
234
+ * gap (its current reply ends), or `failed` with the reason until the next request replaces it.
235
+ */
236
+ /** What one approval asks the user to grant and whether the current grant already covers it. */
237
+ export const ExtensionPermissionRequirementSchema = z
238
+ .object({
239
+ declaration: HostUiPermissionDeclarationSchema,
240
+ permissionDigest: z.string().regex(/^[a-f0-9]{64}$/u),
241
+ approvalRequired: z.boolean(),
242
+ })
243
+ .strict()
244
+
245
+ export type ExtensionPermissionRequirement = z.output<typeof ExtensionPermissionRequirementSchema>
246
+
247
+ export const ExtensionActivationTransitionSchema = z
248
+ .object({
249
+ agentId: AgentIdSchema,
250
+ target: z.enum(['enabled', 'disabled']),
251
+ extensionRevisionId: ExtensionRevisionIdSchema.optional(),
252
+ state: z.enum(['waiting', 'failed']),
253
+ message: z.string().optional(),
254
+ since: z.number().int().safe().nonnegative(),
255
+ })
256
+ .strict()
257
+
217
258
  export const ImageUnderstandingPolicyApiSchema = z
218
259
  .object({
219
260
  history: z
@@ -393,7 +434,15 @@ export const HostSnapshotMessageSchema = z
393
434
  channelId: ChannelIdSchema,
394
435
  role: z.enum(['member', 'agent', 'system']),
395
436
  parts: z.array(SnapshotMessagePartSchema),
396
- sender: z.object({ memberId: ChannelMemberIdSchema, displayName: z.string().optional() }).strict().optional(),
437
+ sender: z
438
+ .object({
439
+ memberId: ChannelMemberIdSchema,
440
+ displayName: z.string().optional(),
441
+ /** The sender is the account of this agent on this host, answering the channel through another connection. */
442
+ localAgentId: AgentIdSchema.optional(),
443
+ })
444
+ .strict()
445
+ .optional(),
397
446
  mentionedConnectionAccount: z.boolean().optional(),
398
447
  activityKey: AdapterActivityKeySchema.optional(),
399
448
  targetLogicalMessageId: LogicalMessageIdSchema.optional(),
@@ -553,6 +602,19 @@ export const ChannelRuntimeStepSchema = z
553
602
  })
554
603
  .strict()
555
604
 
605
+ /** One message that entered the model's input during a turn: channel admissions and host or DSH injections. */
606
+ export const ChannelRuntimeInputSchema = z
607
+ .object({
608
+ messageId: z.string().min(1),
609
+ /** DSH `user/message` source kind, e.g. `nekro-nxt-channel` or `nekro-nxt-handoff`. */
610
+ source: z.string().min(1),
611
+ /** Channel Events carried by a channel admission. */
612
+ eventCount: z.number().int().positive().optional(),
613
+ preview: z.string().optional(),
614
+ at: z.number().int().safe().nonnegative().optional(),
615
+ })
616
+ .strict()
617
+
556
618
  export const ChannelRuntimeTurnSchema = z
557
619
  .object({
558
620
  turn: z.number().int().nonnegative(),
@@ -568,6 +630,8 @@ export const ChannelRuntimeTurnSchema = z
568
630
  endedAt: z.number().int().safe().nonnegative().optional(),
569
631
  /** Newest Channel Event of the admission that opened this turn; absent for non-channel turns. */
570
632
  triggerEventId: ChannelEventIdSchema.optional(),
633
+ /** Messages that entered the model's input during the turn, in log order; absent when there were none. */
634
+ inputs: z.array(ChannelRuntimeInputSchema).optional(),
571
635
  })
572
636
  .strict()
573
637
 
@@ -678,6 +742,62 @@ export const ChannelRuntimeSseDataSchema = ChannelRuntimeProjectionSchema.extend
678
742
  truncated: z.boolean().optional(),
679
743
  }).strict()
680
744
 
745
+ export const ChannelRuntimeContextSchema = z
746
+ .object({
747
+ available: z.boolean(),
748
+ route: z
749
+ .object({
750
+ provider: z.string(),
751
+ model: z.string(),
752
+ contextWindow: z.number().int().positive().optional(),
753
+ reasoningEffort: z.string().optional(),
754
+ temperature: z.number().optional(),
755
+ maxTokens: z.number().int().positive().optional(),
756
+ })
757
+ .strict()
758
+ .optional(),
759
+ instructions: z.array(
760
+ z.object({ role: z.enum(['system', 'developer']), text: z.string(), truncated: z.boolean() }).strict(),
761
+ ),
762
+ tools: z.array(
763
+ z.object({ name: z.string(), description: z.string().optional(), parameters: z.string().optional() }).strict(),
764
+ ),
765
+ changes: z.array(
766
+ z
767
+ .object({
768
+ at: z.number().nonnegative().optional(),
769
+ reason: z.enum(['initial', 'resume', 'change', 'series']),
770
+ toolCount: z.number().int().nonnegative(),
771
+ })
772
+ .strict(),
773
+ ),
774
+ })
775
+ .strict()
776
+
777
+ /** A channel's own instructions for whoever answers it, with recent earlier versions to restore. */
778
+ export const ChannelPromptViewSchema = z
779
+ .object({
780
+ document: PromptDocumentV1Schema,
781
+ /** The agent may not rewrite a locked prompt. */
782
+ locked: z.boolean(),
783
+ /** 0 before the first save; send it back as `expectedRevision`. */
784
+ revision: z.number().int().nonnegative(),
785
+ maxChars: z.number().int().positive(),
786
+ updatedBy: z.enum(['admin', 'agent']).optional(),
787
+ updatedAt: z.number().int().nonnegative().optional(),
788
+ revisions: z.array(
789
+ z
790
+ .object({
791
+ revision: z.number().int().positive(),
792
+ document: PromptDocumentV1Schema,
793
+ updatedBy: z.enum(['admin', 'agent']),
794
+ updatedAt: z.number().int().nonnegative(),
795
+ })
796
+ .strict(),
797
+ ),
798
+ })
799
+ .strict()
800
+
681
801
  export type ChannelRuntimePhase = z.output<typeof ChannelRuntimePhaseSchema>
682
802
  export type ChannelRuntimeUsage = z.output<typeof ChannelRuntimeUsageSchema>
683
803
  export type ChannelRuntimeOccupancy = z.output<typeof ChannelRuntimeOccupancySchema>
@@ -686,6 +806,9 @@ export type ChannelRuntimeCache = z.output<typeof ChannelRuntimeCacheSchema>
686
806
  export type ChannelRuntimePerformanceSample = z.output<typeof ChannelRuntimePerformanceSampleSchema>
687
807
  export type ChannelRuntimePerformance = z.output<typeof ChannelRuntimePerformanceSchema>
688
808
  export type ChannelRuntimeProjection = z.output<typeof ChannelRuntimeProjectionSchema>
809
+ export type ChannelRuntimeContext = z.output<typeof ChannelRuntimeContextSchema>
810
+ export type ChannelRuntimeInput = z.output<typeof ChannelRuntimeInputSchema>
811
+ export type ChannelPromptView = z.output<typeof ChannelPromptViewSchema>
689
812
  export type ChannelRuntimeSseData = z.output<typeof ChannelRuntimeSseDataSchema>
690
813
  export type ChannelFactSseData = z.output<typeof ChannelFactSseDataSchema>
691
814
 
@@ -1074,6 +1197,8 @@ export const HostSnapshotSchema = z
1074
1197
  boundAgentId: AgentIdSchema.optional(),
1075
1198
  runtimePhase: ChannelRuntimePhaseSchema.default('idle'),
1076
1199
  activity: ChannelActivitySummarySchema.default({ unreadCount: 0, unreadCapped: false }),
1200
+ /** Other agents on this host that answer the same platform channel through another connection; absent when none. */
1201
+ localAgentIds: z.array(AgentIdSchema).min(1).optional(),
1077
1202
  bindings: z.array(
1078
1203
  z
1079
1204
  .object({
@@ -1081,6 +1206,8 @@ export const HostSnapshotSchema = z
1081
1206
  agentId: AgentIdSchema,
1082
1207
  triggerPolicy: TriggerPolicySchema,
1083
1208
  processingFeedback: z.enum(['auto', 'off']).default('auto'),
1209
+ /** Absent means `observe`. */
1210
+ localAgentMessages: z.enum(['observe', 'trigger']).optional(),
1084
1211
  activityTriggerOverrides: ActivityTriggerOverridesSchema.default({}),
1085
1212
  boundAt: z.number().int().safe().nonnegative(),
1086
1213
  })
@@ -1160,7 +1287,8 @@ export const HostSnapshotSchema = z
1160
1287
  z
1161
1288
  .object({
1162
1289
  id: ExtensionIdSchema,
1163
- scope: z.enum(['agent', 'host-adapter', 'host-ui']),
1290
+ /** What the latest Revision provides; listing and filtering only. */
1291
+ provides: z.array(ExtensionProvideSchema),
1164
1292
  slug: NonEmptyStringSchema,
1165
1293
  displayName: z.string(),
1166
1294
  description: z.string(),
@@ -1172,11 +1300,21 @@ export const HostSnapshotSchema = z
1172
1300
  revisionNumber: z.number().int().positive(),
1173
1301
  format: z.enum(['current', 'unavailable']).optional(),
1174
1302
  ui: ExtensionUiContributionsSchema.default(EMPTY_EXTENSION_UI_CONTRIBUTIONS),
1175
- configSchema: ConfigSchemaDocumentSchema.optional(),
1303
+ /** The host instance's configuration form (`config.host`). */
1304
+ hostConfigSchema: ConfigSchemaDocumentSchema.optional(),
1305
+ /** Each enabled agent's configuration form (`config.agent`). */
1306
+ agentConfigSchema: ConfigSchemaDocumentSchema.optional(),
1307
+ /** 扩展包自带图标的读取路径(同源、按摘要寻址、可长期缓存);没有图标时缺省。 */
1308
+ iconUrl: z
1309
+ .string()
1310
+ .regex(/^\/api\/extensions\/[^/]+\/revisions\/[^/]+\/icon\/[a-f0-9]{64}\.(?:svg|png|webp)$/u)
1311
+ .optional(),
1176
1312
  createdAt: z.number().int().safe().nonnegative(),
1177
1313
  /** 从社区安装的保存记录的来源;本机保存与文件导入没有来源。 */
1178
1314
  source: CommunitySourceSchema.optional(),
1179
- scope: z.enum(['agent', 'host-adapter', 'host-ui']),
1315
+ provides: z.array(ExtensionProvideSchema),
1316
+ /** Whether this Revision can be enabled for agents (agent-layer contributions or capabilities). */
1317
+ agentLayer: z.boolean(),
1180
1318
  contributions: z.array(z.string()),
1181
1319
  verification: z
1182
1320
  .object({
@@ -1194,12 +1332,11 @@ export const HostSnapshotSchema = z
1194
1332
  renderedPages: z.array(HostPageContributionSchema).max(8).optional(),
1195
1333
  usedUiComponents: z.array(HostUiKitComponentNameSchema).optional(),
1196
1334
  pageGeometry: z.array(HostUiPageGeometryEvidenceSchema).max(8).optional(),
1197
- permissions: HostUiPermissionDeclarationSchema.optional(),
1198
- permissionDigest: z
1199
- .string()
1200
- .regex(/^[a-f0-9]{64}$/u)
1201
- .optional(),
1202
- permissionApprovalRequired: z.boolean().optional(),
1335
+ permissions: ExtensionPermissionsSchema.optional(),
1336
+ /** Installing this Revision on the machine, against the current host grant. */
1337
+ hostPermission: ExtensionPermissionRequirementSchema.optional(),
1338
+ /** Enabling this Revision for an agent that has no grant yet. */
1339
+ agentPermission: ExtensionPermissionRequirementSchema.optional(),
1203
1340
  adapter: z
1204
1341
  .object({
1205
1342
  apiVersion: z.literal(2),
@@ -1253,11 +1390,15 @@ export const HostSnapshotSchema = z
1253
1390
  })
1254
1391
  .strict(),
1255
1392
  ),
1393
+ /** Present only while some agent's enable or disable request is waiting or has failed. */
1394
+ activationTransitions: z.array(ExtensionActivationTransitionSchema).optional(),
1256
1395
  installation: z
1257
1396
  .object({
1258
1397
  extensionRevisionId: ExtensionRevisionIdSchema,
1259
1398
  installedAt: z.number().int().safe().nonnegative(),
1399
+ /** Secret fields are removed; `configuredSecrets` lists those the Host stores. */
1260
1400
  config: JsonValueSchema.default({}),
1401
+ configuredSecrets: z.array(z.string()).optional(),
1261
1402
  runtime: z
1262
1403
  .object({
1263
1404
  status: z.enum(['active', 'restore-failed', 'dispose-failed']),
@@ -1268,14 +1409,8 @@ export const HostSnapshotSchema = z
1268
1409
  })
1269
1410
  .strict()
1270
1411
  .optional(),
1271
- hostUiPermission: z
1272
- .object({
1273
- declaration: HostUiPermissionDeclarationSchema,
1274
- permissionDigest: z.string().regex(/^[a-f0-9]{64}$/u),
1275
- approvalRequired: z.boolean(),
1276
- })
1277
- .strict()
1278
- .optional(),
1412
+ /** Installing the latest Revision on this machine, against the current host grant. */
1413
+ hostPermission: ExtensionPermissionRequirementSchema.optional(),
1279
1414
  hostClientDiagnostic: z
1280
1415
  .object({
1281
1416
  revisionId: ExtensionRevisionIdSchema,
@@ -1618,6 +1753,22 @@ export const LlmProviderCredentialSchema = z
1618
1753
  .object({ configured: z.boolean(), source: z.string().optional(), writable: z.boolean() })
1619
1754
  .strict()
1620
1755
 
1756
+ /**
1757
+ * The latest connection test that still describes the provider's saved address, protocol and API key. Tests made
1758
+ * before one of those changed are dropped. Never carries a key, request or response body.
1759
+ */
1760
+ export const LlmProviderTestResultSchema = z
1761
+ .object({
1762
+ /** Epoch milliseconds when the test finished. */
1763
+ at: z.number().int().nonnegative(),
1764
+ ok: z.boolean(),
1765
+ /** Short failure reason shown to the user; absent when the test passed. */
1766
+ message: z.string().max(240).optional(),
1767
+ /** The model the test asked. */
1768
+ model: NonEmptyStringSchema.optional(),
1769
+ })
1770
+ .strict()
1771
+
1621
1772
  export const LlmProviderViewSchema = z
1622
1773
  .object({
1623
1774
  provider: NonEmptyStringSchema,
@@ -1636,6 +1787,8 @@ export const LlmProviderViewSchema = z
1636
1787
  modelsCustomized: z.boolean(),
1637
1788
  /** The provider's adapter can list the models its endpoint offers. */
1638
1789
  discoverable: z.boolean(),
1790
+ /** `null` when the current configuration was never tested; absent from hosts that do not record tests. */
1791
+ lastTest: LlmProviderTestResultSchema.nullable().optional(),
1639
1792
  })
1640
1793
  .strict()
1641
1794
 
@@ -1715,7 +1868,7 @@ export const ExtensionImportInspectionSchema = z
1715
1868
  revisionId: ExtensionRevisionIdSchema,
1716
1869
  slug: NonEmptyStringSchema,
1717
1870
  displayName: NonEmptyStringSchema,
1718
- scope: z.enum(['agent', 'host-adapter', 'host-ui']),
1871
+ provides: z.array(ExtensionProvideSchema),
1719
1872
  idempotent: z.boolean(),
1720
1873
  slugConflict: z.boolean(),
1721
1874
  })
@@ -1775,6 +1928,8 @@ export type AgentRevisionHistory = z.output<typeof AgentRevisionHistorySchema>
1775
1928
  const channelParam = z.object({ channelId: ChannelIdSchema }).strict()
1776
1929
  const connectionParam = z.object({ connectionId: ConnectionIdSchema }).strict()
1777
1930
  const agentExtensionParam = z.object({ agentId: AgentIdSchema, extensionId: ExtensionIdSchema }).strict()
1931
+
1932
+ const PermissionApprovalSchema = z.object({ permissionDigest: z.string().regex(/^[a-f0-9]{64}$/u) }).strict()
1778
1933
  const extensionParam = z.object({ extensionId: ExtensionIdSchema }).strict()
1779
1934
  const dshPluginPackageParam = z.object({ packageId: DshPluginPackageIdSchema }).strict()
1780
1935
  const dshPluginEntryParam = z.object({ entryId: DshPluginEntryIdSchema }).strict()
@@ -2110,6 +2265,8 @@ export const HostApiContracts = {
2110
2265
  channelId: ChannelIdSchema,
2111
2266
  triggerPolicy: TriggerPolicySchema,
2112
2267
  processingFeedback: z.enum(['auto', 'off']).optional(),
2268
+ /** Messages from another local agent's account: `observe` keeps them as context unless they @ this agent. */
2269
+ localAgentMessages: z.enum(['observe', 'trigger']).optional(),
2113
2270
  activityTriggerOverrides: ActivityTriggerOverridesSchema.optional(),
2114
2271
  })
2115
2272
  .strict(),
@@ -2119,6 +2276,7 @@ export const HostApiContracts = {
2119
2276
  agentId: AgentIdSchema,
2120
2277
  triggerPolicy: TriggerPolicySchema,
2121
2278
  processingFeedback: z.enum(['auto', 'off']).default('auto'),
2279
+ localAgentMessages: z.enum(['observe', 'trigger']).optional(),
2122
2280
  activityTriggerOverrides: ActivityTriggerOverridesSchema.default({}),
2123
2281
  boundAt: z.number().int().safe().nonnegative(),
2124
2282
  })
@@ -2215,6 +2373,57 @@ export const HostApiContracts = {
2215
2373
  .strict(),
2216
2374
  error: HostApiErrorSchema,
2217
2375
  }),
2376
+ getChannelRuntimeContext: defineContract({
2377
+ method: 'GET',
2378
+ path: '/api/channels/:channelId/runtime/context',
2379
+ params: channelParam,
2380
+ request: NoRequestBodySchema,
2381
+ // What the live session sends the model: route, rendered instructions and tool schemas. Read on demand; the runtime
2382
+ // projection pushed over SSE never carries it. `available: false` when no session of the channel is in memory.
2383
+ response: ChannelRuntimeContextSchema,
2384
+ error: HostApiErrorSchema,
2385
+ }),
2386
+ getChannelRuntimeInput: defineContract({
2387
+ method: 'GET',
2388
+ path: '/api/channels/:channelId/runtime/inputs/:messageId',
2389
+ params: z.object({ channelId: ChannelIdSchema, messageId: z.string().trim().min(1).max(200) }).strict(),
2390
+ request: NoRequestBodySchema,
2391
+ // The full text of one input message as the model received it; the runtime projection only carries a preview.
2392
+ // `available: false` when the session has left memory.
2393
+ response: z
2394
+ .object({
2395
+ messageId: z.string(),
2396
+ available: z.boolean(),
2397
+ source: z.string().optional(),
2398
+ text: z.string().optional(),
2399
+ truncated: z.boolean(),
2400
+ })
2401
+ .strict(),
2402
+ error: HostApiErrorSchema,
2403
+ }),
2404
+ getChannelPrompt: defineContract({
2405
+ method: 'GET',
2406
+ path: '/api/channels/:channelId/prompt',
2407
+ params: channelParam,
2408
+ request: NoRequestBodySchema,
2409
+ response: ChannelPromptViewSchema,
2410
+ error: HostApiErrorSchema,
2411
+ }),
2412
+ updateChannelPrompt: defineContract({
2413
+ method: 'PUT',
2414
+ path: '/api/channels/:channelId/prompt',
2415
+ params: channelParam,
2416
+ request: z
2417
+ .object({
2418
+ document: PromptDocumentV1Schema,
2419
+ locked: z.boolean(),
2420
+ /** The revision the edit started from; a newer stored revision rejects the save. */
2421
+ expectedRevision: z.number().int().nonnegative(),
2422
+ })
2423
+ .strict(),
2424
+ response: ChannelPromptViewSchema,
2425
+ error: HostApiErrorSchema,
2426
+ }),
2218
2427
  resetChannelContext: defineContract({
2219
2428
  invalidatesSnapshot: true,
2220
2429
  method: 'POST',
@@ -2528,7 +2737,11 @@ export const HostApiContracts = {
2528
2737
  params: z
2529
2738
  .object({
2530
2739
  query: z.string().trim().max(80).optional(),
2531
- scope: z.enum(['agent', 'host-adapter', 'host-ui']).optional(),
2740
+ provides: ExtensionProvideSchema.optional(),
2741
+ /** 只列社区后台认定的官方扩展。 */
2742
+ official: z.enum(['1']).optional(),
2743
+ /** 排序方式,默认最近更新;游标只在同一种排序下有效。 */
2744
+ sort: CommunityExtensionSortSchema.optional(),
2532
2745
  cursor: z.string().max(200).optional(),
2533
2746
  })
2534
2747
  .strict(),
@@ -2643,6 +2856,8 @@ export const HostApiContracts = {
2643
2856
  extensionId: ExtensionIdSchema,
2644
2857
  revisionId: ExtensionRevisionIdSchema,
2645
2858
  notes: z.string().max(2000),
2859
+ /** 作者填写的条目信息;省略的字段不改动社区上已有的内容。 */
2860
+ listing: CommunityListingInputSchema.optional(),
2646
2861
  })
2647
2862
  .strict(),
2648
2863
  response: z
@@ -2656,6 +2871,114 @@ export const HostApiContracts = {
2656
2871
  .strict(),
2657
2872
  error: HostApiErrorSchema,
2658
2873
  }),
2874
+ listCommunityPersonas: defineContract({
2875
+ timeoutMs: 30_000,
2876
+ method: 'GET',
2877
+ path: '/api/community/personas',
2878
+ params: z
2879
+ .object({
2880
+ query: z.string().trim().min(1).max(200).optional(),
2881
+ tag: z.string().trim().min(1).max(40).optional(),
2882
+ official: z.literal('1').optional(),
2883
+ cursor: z.string().min(1).max(500).optional(),
2884
+ })
2885
+ .strict(),
2886
+ request: NoRequestBodySchema,
2887
+ response: z.object({ items: z.array(CommunityPersonaSummarySchema), nextCursor: z.string().nullable() }).strict(),
2888
+ error: HostApiErrorSchema,
2889
+ }),
2890
+ getCommunityPersona: defineContract({
2891
+ timeoutMs: 30_000,
2892
+ method: 'GET',
2893
+ path: '/api/community/personas/:personaId',
2894
+ params: z.object({ personaId: CommunityPersonaIdSchema }).strict(),
2895
+ request: NoRequestBodySchema,
2896
+ response: CommunityPersonaDetailSchema,
2897
+ error: HostApiErrorSchema,
2898
+ }),
2899
+ /**
2900
+ * 把社区人设装进本机:新建一个智能体,或为现有智能体保存一次只换设定(及可选名称)的新配置。头像下载后作为
2901
+ * 智能体头像;下载失败不影响安装。`expectedRevisionId` 是用户看过的修订,社区已更新时拒绝,避免装入未看过的内容。
2902
+ */
2903
+ installCommunityPersona: defineContract({
2904
+ invalidatesSnapshot: true,
2905
+ timeoutMs: 60_000,
2906
+ method: 'POST',
2907
+ path: '/api/community/personas/:personaId/install',
2908
+ params: z.object({ personaId: CommunityPersonaIdSchema }).strict(),
2909
+ request: z.discriminatedUnion('target', [
2910
+ z
2911
+ .object({
2912
+ target: z.literal('new'),
2913
+ expectedRevisionId: CommunityPersonaRevisionIdSchema,
2914
+ displayName: z.string().trim().min(1).max(80),
2915
+ model: AgentModelSchema,
2916
+ useAvatar: z.boolean(),
2917
+ })
2918
+ .strict(),
2919
+ z
2920
+ .object({
2921
+ target: z.literal('replace'),
2922
+ expectedRevisionId: CommunityPersonaRevisionIdSchema,
2923
+ agentId: AgentIdSchema,
2924
+ expectedCurrentRevisionId: AgentRevisionIdSchema,
2925
+ /** 同时改名;省略时保留原名称。 */
2926
+ displayName: z.string().trim().min(1).max(80).optional(),
2927
+ useAvatar: z.boolean(),
2928
+ })
2929
+ .strict(),
2930
+ ]),
2931
+ response: z
2932
+ .object({
2933
+ agentId: AgentIdSchema,
2934
+ channelId: ChannelIdSchema.nullable(),
2935
+ currentRevisionId: AgentRevisionIdSchema,
2936
+ avatar: z.enum(['applied', 'none', 'failed']),
2937
+ })
2938
+ .strict(),
2939
+ error: HostApiErrorSchema,
2940
+ }),
2941
+ listCommunityMyPersonas: defineContract({
2942
+ timeoutMs: 30_000,
2943
+ method: 'GET',
2944
+ path: '/api/community/mine/personas',
2945
+ params: EmptyParamsSchema,
2946
+ request: NoRequestBodySchema,
2947
+ response: CommunityMyPersonasSchema,
2948
+ error: HostApiErrorSchema,
2949
+ }),
2950
+ /** 把智能体的设定分享到社区;带 `personaId` 时更新自己已发布的人设(生成新修订并重新审查)。 */
2951
+ publishCommunityPersona: defineContract({
2952
+ timeoutMs: 60_000,
2953
+ method: 'POST',
2954
+ path: '/api/community/personas/publish',
2955
+ params: EmptyParamsSchema,
2956
+ request: z
2957
+ .object({
2958
+ agentId: AgentIdSchema,
2959
+ personaId: CommunityPersonaIdSchema.optional(),
2960
+ name: z.string().trim().min(1).max(80),
2961
+ summary: z.string().trim().min(1).max(200),
2962
+ description: z.string().max(20_000),
2963
+ tags: z.array(z.string().trim().min(1).max(40)).max(16),
2964
+ persona: z.string().trim().min(1).max(COMMUNITY_PERSONA_MAX_LENGTH),
2965
+ notes: z.string().max(2000).optional(),
2966
+ /** 页面缩放后的头像(Base64);省略时不上传头像,更新时保留社区上的原头像。 */
2967
+ avatar: z
2968
+ .object({
2969
+ mediaType: z.enum(COMMUNITY_PERSONA_AVATAR_TYPES),
2970
+ base64: z
2971
+ .string()
2972
+ .min(1)
2973
+ .max(Math.ceil((512 * 1024 * 4) / 3) + 4),
2974
+ })
2975
+ .strict()
2976
+ .optional(),
2977
+ })
2978
+ .strict(),
2979
+ response: CommunityMyPersonaSchema,
2980
+ error: HostApiErrorSchema,
2981
+ }),
2659
2982
  testMcpServer: defineContract({
2660
2983
  timeoutMs: 30_000,
2661
2984
  method: 'POST',
@@ -3112,8 +3435,19 @@ export const HostApiContracts = {
3112
3435
  method: 'POST',
3113
3436
  path: '/api/extensions/:extensionId/revisions/:revisionId/call',
3114
3437
  params: extensionRevisionParam,
3438
+ /**
3439
+ * A panel's call to its extension's host instance. The Host checks the anchor (the agent has the extension
3440
+ * enabled; the channel or connection exists) and hands the extension the resolved caller.
3441
+ */
3115
3442
  request: z
3116
- .object({ agentId: AgentIdSchema, method: NonEmptyStringSchema, input: JsonValueSchema.optional() })
3443
+ .object({
3444
+ /** Absent: the call comes from the extension itself, like a page call. */
3445
+ anchor: z.object({ kind: ExtensionPanelAnchorSchema, id: NonEmptyStringSchema }).strict().optional(),
3446
+ /** The agent the panel is shown for; must be the responding agent of an anchored channel. */
3447
+ agentId: AgentIdSchema.optional(),
3448
+ method: NonEmptyStringSchema,
3449
+ input: JsonValueSchema.optional(),
3450
+ })
3117
3451
  .strict(),
3118
3452
  response: z.object({ value: JsonValueSchema }).strict(),
3119
3453
  error: HostApiErrorSchema,
@@ -3148,12 +3482,16 @@ export const HostApiContracts = {
3148
3482
  request: z
3149
3483
  .object({
3150
3484
  revisionId: ExtensionRevisionIdSchema,
3151
- permissionApproval: z
3152
- .object({ permissionDigest: z.string().regex(/^[a-f0-9]{64}$/u) })
3153
- .strict()
3154
- .optional(),
3485
+ /** Approval of the agent-layer capabilities. */
3486
+ permissionApproval: PermissionApprovalSchema.optional(),
3487
+ /** Approval of the host layer when enabling also installs or switches the extension on this machine. */
3488
+ hostPermissionApproval: PermissionApprovalSchema.optional(),
3155
3489
  })
3156
3490
  .strict(),
3491
+ /**
3492
+ * The committed Activation, or — while the agent is still replying — `pending` with the accepted request; it then
3493
+ * takes effect at the agent's next safe gap and its progress appears in the snapshot's `activationTransitions`.
3494
+ */
3157
3495
  response: z
3158
3496
  .object({
3159
3497
  activation: z
@@ -3165,9 +3503,12 @@ export const HostApiContracts = {
3165
3503
  configuredSecrets: z.array(z.string()).optional(),
3166
3504
  activatedAt: z.number().int().safe().nonnegative(),
3167
3505
  })
3168
- .strict(),
3506
+ .strict()
3507
+ .optional(),
3508
+ pending: ExtensionActivationTransitionSchema.optional(),
3169
3509
  })
3170
- .strict(),
3510
+ .strict()
3511
+ .refine((value) => (value.activation === undefined) !== (value.pending === undefined), '启用结果必须二选一。'),
3171
3512
  error: HostApiErrorSchema,
3172
3513
  }),
3173
3514
  deactivateExtension: defineContract({
@@ -3176,7 +3517,8 @@ export const HostApiContracts = {
3176
3517
  path: '/api/agents/:agentId/extensions/:extensionId/activation',
3177
3518
  params: agentExtensionParam,
3178
3519
  request: NoRequestBodySchema,
3179
- response: z.object({ disabled: z.literal(true) }).strict(),
3520
+ /** `pending` is present when the agent is still replying; the Activation is removed at its next safe gap. */
3521
+ response: z.object({ disabled: z.literal(true), pending: ExtensionActivationTransitionSchema.optional() }).strict(),
3180
3522
  error: HostApiErrorSchema,
3181
3523
  }),
3182
3524
  updateExtensionActivationConfig: defineContract({
@@ -3200,8 +3542,14 @@ export const HostApiContracts = {
3200
3542
  method: 'PUT',
3201
3543
  path: '/api/extensions/:extensionId/installation/config',
3202
3544
  params: extensionParam,
3203
- request: z.object({ config: JsonValueSchema }).strict(),
3204
- response: z.object({ config: JsonValueSchema }).strict(),
3545
+ request: z
3546
+ .object({
3547
+ config: JsonValueSchema,
3548
+ /** Write-only credential drafts keyed by secret field; an absent or empty draft keeps the stored one. */
3549
+ secrets: z.record(z.string(), z.string().max(8192)).optional(),
3550
+ })
3551
+ .strict(),
3552
+ response: z.object({ config: JsonValueSchema, configuredSecrets: z.array(z.string()).optional() }).strict(),
3205
3553
  error: HostApiErrorSchema,
3206
3554
  }),
3207
3555
  installHostExtension: defineContract({
@@ -3213,10 +3561,10 @@ export const HostApiContracts = {
3213
3561
  request: z
3214
3562
  .object({
3215
3563
  revisionId: ExtensionRevisionIdSchema,
3216
- permissionApproval: z
3217
- .object({ permissionDigest: z.string().regex(/^[a-f0-9]{64}$/u) })
3218
- .strict()
3219
- .optional(),
3564
+ /** Approval of the host layer (browser permissions and `permissions.host`). */
3565
+ permissionApproval: PermissionApprovalSchema.optional(),
3566
+ /** Approval of expanded agent-layer capabilities for the agents that move to this Revision. */
3567
+ agentPermissionApproval: PermissionApprovalSchema.optional(),
3220
3568
  })
3221
3569
  .strict(),
3222
3570
  response: z
package/src/index.ts CHANGED
@@ -6,3 +6,4 @@ export * from './management-api.js'
6
6
  export * from './runtime-compatibility.js'
7
7
  export * from './extension-capabilities.js'
8
8
  export * from './community.js'
9
+ export * from './community-personas.js'