@native-knowledge/knowledge-sdk 0.1.0-rc.1 → 0.1.0-rc.2

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 (206) hide show
  1. package/LICENSE +202 -21
  2. package/NOTICE +29 -0
  3. package/README.md +26 -38
  4. package/dist/{types/sdk/agent-entry.d.ts → agent-entry.d.ts} +3 -3
  5. package/dist/agent-entry.js +153 -0
  6. package/dist/{types/sdk/agent-guidance-error.d.ts → agent-guidance-error.d.ts} +1 -1
  7. package/dist/agent-guidance-error.js +46 -0
  8. package/dist/auth.d.ts +124 -0
  9. package/dist/auth.js +165 -0
  10. package/dist/{types/sdk/index.d.ts → index.d.ts} +15 -14
  11. package/dist/index.js +159 -6570
  12. package/dist/internal/contracts/artifact.js +103 -0
  13. package/dist/internal/contracts/collection-control.js +69 -0
  14. package/dist/internal/contracts/collection.js +174 -0
  15. package/dist/internal/contracts/common.js +16 -0
  16. package/dist/internal/contracts/currentness.js +221 -0
  17. package/dist/internal/contracts/event.js +35 -0
  18. package/dist/internal/contracts/evidence.js +171 -0
  19. package/dist/{types → internal}/contracts/index.d.ts +0 -1
  20. package/dist/internal/contracts/index.js +54 -0
  21. package/dist/internal/contracts/material-capability.js +8 -0
  22. package/dist/internal/contracts/material-carrier.js +15 -0
  23. package/dist/internal/contracts/material-context.js +9 -0
  24. package/dist/internal/contracts/material-read.js +12 -0
  25. package/dist/internal/contracts/observation.js +39 -0
  26. package/dist/internal/contracts/persistence.js +239 -0
  27. package/dist/internal/contracts/project-intent.js +121 -0
  28. package/dist/internal/contracts/projection.js +194 -0
  29. package/dist/internal/contracts/public-reference.js +87 -0
  30. package/dist/internal/contracts/reference-record.js +55 -0
  31. package/dist/internal/contracts/remote-file.js +159 -0
  32. package/dist/internal/contracts/resource-scope.js +38 -0
  33. package/dist/internal/contracts/review-packet.js +61 -0
  34. package/dist/internal/contracts/review-plane.js +89 -0
  35. package/dist/internal/contracts/rich-document.js +184 -0
  36. package/dist/internal/contracts/runtime-compatibility.js +55 -0
  37. package/dist/internal/contracts/runtime.js +68 -0
  38. package/dist/internal/contracts/scheduler.js +256 -0
  39. package/dist/internal/contracts/signal.js +77 -0
  40. package/dist/internal/contracts/source-governance.js +194 -0
  41. package/dist/internal/contracts/source.js +32 -0
  42. package/dist/internal/contracts/tenant-budget.js +34 -0
  43. package/dist/internal/contracts/tenant-collection-request.js +58 -0
  44. package/dist/internal/contracts/tenant-collection.js +66 -0
  45. package/dist/internal/contracts/tenant-currentness.js +26 -0
  46. package/dist/internal/contracts/tenant-management.js +27 -0
  47. package/dist/internal/contracts/tenant-material-api.js +46 -0
  48. package/dist/internal/contracts/tenant-material-json-schema.js +16 -0
  49. package/dist/internal/contracts/tenant-pdf-text.js +13 -0
  50. package/dist/internal/contracts/tenant-project-control.js +19 -0
  51. package/dist/internal/contracts/tenant-public-reference.js +26 -0
  52. package/dist/internal/contracts/tenant-resource-api.js +70 -0
  53. package/dist/internal/contracts/tenant-resource.js +118 -0
  54. package/dist/internal/contracts/tenant-rich-document.js +17 -0
  55. package/dist/internal/contracts/tenant-source-binding.js +33 -0
  56. package/dist/internal/contracts/tenant-source-bridge.js +9 -0
  57. package/dist/internal/contracts/tenant-source-cutover.js +26 -0
  58. package/dist/internal/contracts/tenant-source-document.js +38 -0
  59. package/dist/internal/contracts/tenant-source-lease.js +5 -0
  60. package/dist/internal/contracts/tenant-source.js +83 -0
  61. package/dist/internal/contracts/tenant-web-collection.js +118 -0
  62. package/dist/internal/contracts/tenant-web-content-plan.js +39 -0
  63. package/dist/internal/contracts/tenant-web-content-result.js +15 -0
  64. package/dist/internal/contracts/tenant-web-content.js +16 -0
  65. package/dist/internal/contracts/tenant-web-crawl.js +55 -0
  66. package/dist/internal/contracts/tenant-web-dynamic.js +68 -0
  67. package/dist/internal/contracts/tenant-web-results.js +41 -0
  68. package/dist/internal/contracts/tenant-web-workflow.js +29 -0
  69. package/dist/internal/serving-contracts/agent-catalog.js +56 -0
  70. package/dist/internal/serving-contracts/agent-entry.js +57 -0
  71. package/dist/internal/serving-contracts/agent-guidance-shapes.js +12 -0
  72. package/dist/internal/serving-contracts/agent-input-hints.js +104 -0
  73. package/dist/internal/serving-contracts/body-search.js +16 -0
  74. package/dist/internal/serving-contracts/consumer.js +45 -0
  75. package/dist/internal/serving-contracts/core.js +76 -0
  76. package/dist/internal/serving-contracts/http.js +64 -0
  77. package/dist/{types → internal}/serving-contracts/index.d.ts +1 -0
  78. package/dist/internal/serving-contracts/index.js +25 -0
  79. package/dist/internal/serving-contracts/management.js +15 -0
  80. package/dist/internal/serving-contracts/material-capabilities.js +14 -0
  81. package/dist/internal/serving-contracts/material-index-status.js +5 -0
  82. package/dist/internal/serving-contracts/mcp.js +140 -0
  83. package/dist/internal/serving-contracts/tenant-governance.js +13 -0
  84. package/dist/internal/serving-contracts/tenant-management.js +89 -0
  85. package/dist/internal/serving-contracts/tenant-project.js +39 -0
  86. package/dist/internal/serving-contracts/tenant-runtime.js +37 -0
  87. package/dist/internal/serving-contracts/tenant-session.d.ts +87 -0
  88. package/dist/internal/serving-contracts/tenant-session.js +8 -0
  89. package/dist/internal/serving-contracts/tenant-web-content.js +20 -0
  90. package/dist/internal/serving-contracts/tenant-web-crawl.js +13 -0
  91. package/dist/internal/serving-contracts/tenant-web-dynamic.js +20 -0
  92. package/dist/internal/serving-contracts/tenant-web-workflow.js +36 -0
  93. package/dist/internal/serving-contracts/tenant-web.js +53 -0
  94. package/dist/internal/serving-contracts/tenant-workspace.js +28 -0
  95. package/dist/internal/serving-contracts/workflow.js +37 -0
  96. package/dist/material-stream.js +29 -0
  97. package/dist/{types/sdk/oauth.d.ts → oauth.d.ts} +18 -18
  98. package/dist/oauth.js +539 -0
  99. package/dist/{types/sdk/resource.d.ts → resource.d.ts} +5 -5
  100. package/dist/resource.js +123 -0
  101. package/dist/session.d.ts +4 -0
  102. package/dist/session.js +3 -0
  103. package/dist/tenant-client.d.ts +169 -0
  104. package/dist/tenant-client.js +58 -0
  105. package/dist/{types/sdk/tenant-management.d.ts → tenant-management.d.ts} +6 -6
  106. package/dist/tenant-management.js +149 -0
  107. package/dist/{types/sdk/tenant-project.d.ts → tenant-project.d.ts} +1 -1
  108. package/dist/tenant-project.js +63 -0
  109. package/dist/{types/sdk/tenant-runtime.d.ts → tenant-runtime.d.ts} +1 -1
  110. package/dist/tenant-runtime.js +17 -0
  111. package/dist/{types/sdk/tenant-web-content.d.ts → tenant-web-content.d.ts} +1 -1
  112. package/dist/tenant-web-content.js +70 -0
  113. package/dist/{types/sdk/tenant-web-crawl.d.ts → tenant-web-crawl.d.ts} +1 -1
  114. package/dist/tenant-web-crawl.js +39 -0
  115. package/dist/{types/sdk/tenant-web-dynamic.d.ts → tenant-web-dynamic.d.ts} +1 -1
  116. package/dist/tenant-web-dynamic.js +39 -0
  117. package/dist/{types/sdk/tenant-web-workflow.d.ts → tenant-web-workflow.d.ts} +1 -1
  118. package/dist/tenant-web-workflow.js +63 -0
  119. package/dist/{types/sdk/tenant-web.d.ts → tenant-web.d.ts} +1 -1
  120. package/dist/tenant-web.js +39 -0
  121. package/dist/{types/sdk/tenant-workspace.d.ts → tenant-workspace.d.ts} +1 -1
  122. package/dist/tenant-workspace.js +21 -0
  123. package/dist/token-provider.d.ts +14 -0
  124. package/dist/token-provider.js +21 -0
  125. package/package.json +27 -15
  126. package/dist/types/contracts/resource-transfer.d.ts +0 -24
  127. package/dist/types/sdk/resource-integrity.d.ts +0 -21
  128. package/dist/types/sdk/transport.d.ts +0 -16
  129. /package/dist/{types → internal}/contracts/artifact.d.ts +0 -0
  130. /package/dist/{types → internal}/contracts/collection-control.d.ts +0 -0
  131. /package/dist/{types → internal}/contracts/collection.d.ts +0 -0
  132. /package/dist/{types → internal}/contracts/common.d.ts +0 -0
  133. /package/dist/{types → internal}/contracts/currentness.d.ts +0 -0
  134. /package/dist/{types → internal}/contracts/event.d.ts +0 -0
  135. /package/dist/{types → internal}/contracts/evidence.d.ts +0 -0
  136. /package/dist/{types → internal}/contracts/material-capability.d.ts +0 -0
  137. /package/dist/{types → internal}/contracts/material-carrier.d.ts +0 -0
  138. /package/dist/{types → internal}/contracts/material-context.d.ts +0 -0
  139. /package/dist/{types → internal}/contracts/material-read.d.ts +0 -0
  140. /package/dist/{types → internal}/contracts/observation.d.ts +0 -0
  141. /package/dist/{types → internal}/contracts/persistence.d.ts +0 -0
  142. /package/dist/{types → internal}/contracts/project-intent.d.ts +0 -0
  143. /package/dist/{types → internal}/contracts/projection.d.ts +0 -0
  144. /package/dist/{types → internal}/contracts/public-reference.d.ts +0 -0
  145. /package/dist/{types → internal}/contracts/reference-record.d.ts +0 -0
  146. /package/dist/{types → internal}/contracts/remote-file.d.ts +0 -0
  147. /package/dist/{types → internal}/contracts/resource-scope.d.ts +0 -0
  148. /package/dist/{types → internal}/contracts/review-packet.d.ts +0 -0
  149. /package/dist/{types → internal}/contracts/review-plane.d.ts +0 -0
  150. /package/dist/{types → internal}/contracts/rich-document.d.ts +0 -0
  151. /package/dist/{types → internal}/contracts/runtime-compatibility.d.ts +0 -0
  152. /package/dist/{types → internal}/contracts/runtime.d.ts +0 -0
  153. /package/dist/{types → internal}/contracts/scheduler.d.ts +0 -0
  154. /package/dist/{types → internal}/contracts/signal.d.ts +0 -0
  155. /package/dist/{types → internal}/contracts/source-governance.d.ts +0 -0
  156. /package/dist/{types → internal}/contracts/source.d.ts +0 -0
  157. /package/dist/{types → internal}/contracts/tenant-budget.d.ts +0 -0
  158. /package/dist/{types → internal}/contracts/tenant-collection-request.d.ts +0 -0
  159. /package/dist/{types → internal}/contracts/tenant-collection.d.ts +0 -0
  160. /package/dist/{types → internal}/contracts/tenant-currentness.d.ts +0 -0
  161. /package/dist/{types → internal}/contracts/tenant-management.d.ts +0 -0
  162. /package/dist/{types → internal}/contracts/tenant-material-api.d.ts +0 -0
  163. /package/dist/{types → internal}/contracts/tenant-pdf-text.d.ts +0 -0
  164. /package/dist/{types → internal}/contracts/tenant-project-control.d.ts +0 -0
  165. /package/dist/{types → internal}/contracts/tenant-public-reference.d.ts +0 -0
  166. /package/dist/{types → internal}/contracts/tenant-resource-api.d.ts +0 -0
  167. /package/dist/{types → internal}/contracts/tenant-resource.d.ts +0 -0
  168. /package/dist/{types → internal}/contracts/tenant-rich-document.d.ts +0 -0
  169. /package/dist/{types → internal}/contracts/tenant-source-binding.d.ts +0 -0
  170. /package/dist/{types → internal}/contracts/tenant-source-bridge.d.ts +0 -0
  171. /package/dist/{types → internal}/contracts/tenant-source-cutover.d.ts +0 -0
  172. /package/dist/{types → internal}/contracts/tenant-source-document.d.ts +0 -0
  173. /package/dist/{types → internal}/contracts/tenant-source-lease.d.ts +0 -0
  174. /package/dist/{types → internal}/contracts/tenant-source.d.ts +0 -0
  175. /package/dist/{types → internal}/contracts/tenant-web-collection.d.ts +0 -0
  176. /package/dist/{types → internal}/contracts/tenant-web-content-plan.d.ts +0 -0
  177. /package/dist/{types → internal}/contracts/tenant-web-content-result.d.ts +0 -0
  178. /package/dist/{types → internal}/contracts/tenant-web-content.d.ts +0 -0
  179. /package/dist/{types → internal}/contracts/tenant-web-crawl.d.ts +0 -0
  180. /package/dist/{types → internal}/contracts/tenant-web-dynamic.d.ts +0 -0
  181. /package/dist/{types → internal}/contracts/tenant-web-results.d.ts +0 -0
  182. /package/dist/{types → internal}/contracts/tenant-web-workflow.d.ts +0 -0
  183. /package/dist/{types → internal}/serving-contracts/agent-catalog.d.ts +0 -0
  184. /package/dist/{types → internal}/serving-contracts/agent-entry.d.ts +0 -0
  185. /package/dist/{types → internal}/serving-contracts/agent-guidance-shapes.d.ts +0 -0
  186. /package/dist/{types → internal}/serving-contracts/agent-input-hints.d.ts +0 -0
  187. /package/dist/{types → internal}/serving-contracts/body-search.d.ts +0 -0
  188. /package/dist/{types → internal}/serving-contracts/consumer.d.ts +0 -0
  189. /package/dist/{types → internal}/serving-contracts/core.d.ts +0 -0
  190. /package/dist/{types → internal}/serving-contracts/http.d.ts +0 -0
  191. /package/dist/{types → internal}/serving-contracts/management.d.ts +0 -0
  192. /package/dist/{types → internal}/serving-contracts/material-capabilities.d.ts +0 -0
  193. /package/dist/{types → internal}/serving-contracts/material-index-status.d.ts +0 -0
  194. /package/dist/{types → internal}/serving-contracts/mcp.d.ts +0 -0
  195. /package/dist/{types → internal}/serving-contracts/tenant-governance.d.ts +0 -0
  196. /package/dist/{types → internal}/serving-contracts/tenant-management.d.ts +0 -0
  197. /package/dist/{types → internal}/serving-contracts/tenant-project.d.ts +0 -0
  198. /package/dist/{types → internal}/serving-contracts/tenant-runtime.d.ts +0 -0
  199. /package/dist/{types → internal}/serving-contracts/tenant-web-content.d.ts +0 -0
  200. /package/dist/{types → internal}/serving-contracts/tenant-web-crawl.d.ts +0 -0
  201. /package/dist/{types → internal}/serving-contracts/tenant-web-dynamic.d.ts +0 -0
  202. /package/dist/{types → internal}/serving-contracts/tenant-web-workflow.d.ts +0 -0
  203. /package/dist/{types → internal}/serving-contracts/tenant-web.d.ts +0 -0
  204. /package/dist/{types → internal}/serving-contracts/tenant-workspace.d.ts +0 -0
  205. /package/dist/{types → internal}/serving-contracts/workflow.d.ts +0 -0
  206. /package/dist/{types/sdk/material-stream.d.ts → material-stream.d.ts} +0 -0
@@ -0,0 +1,140 @@
1
+ import { materialCapabilityResponseSchema, materialMediaCapabilityPageSchema } from './material-capabilities.js';
2
+ import { materialIndexStatusSchema } from './material-index-status.js';
3
+ import { materialResourceTypeSchema } from '../contracts/index.js';
4
+ import { z } from 'zod';
5
+ import { projectKeySchema, schemaVersionSchema, stableUriSchema, sha256Schema } from '../contracts/index.js';
6
+ import { consumerCurrentnessResponseSchema, consumerEvidencePageResponseSchema, consumerProjectRefSchema, consumerReadResponseSchema, consumerReferenceLookupResponseSchema, consumerSearchResponseSchema } from './consumer.js';
7
+ import { materialOutboxWindowSchema, materialRoutePartitionSchema, servingMaterialDirectoryItemSchema } from './http.js';
8
+ export const knowledgeMcpProtocolVersion = '2026-07-28';
9
+ export const knowledgeMcpToolNameSchema = z.enum(['knowledge_search', 'knowledge_read', 'knowledge_currentness', 'knowledge_reference_lookup']);
10
+ export const knowledgeMcpToolNameV2Schema = z.enum(['knowledge_search', 'knowledge_read', 'knowledge_currentness', 'knowledge_reference_lookup', 'knowledge_list_evidence']);
11
+ export const knowledgeMcpScopeSchema = z.enum(['knowledge.search', 'knowledge.read', 'knowledge.currentness']);
12
+ export const knowledgeMcpProviderContractSchema = z.object({
13
+ schemaVersion: schemaVersionSchema, provider: z.literal('knowledge-v2'), revision: z.string().trim().min(7).max(64), protocolVersion: z.literal(knowledgeMcpProtocolVersion),
14
+ validationStatus: z.enum(['NOT_VERIFIED', 'RUNTIME_CONFIGURED']), externalReachability: z.literal('NOT_VERIFIED'), endpoint: z.string().url().nullable(), mediaEndpoint: z.string().url().nullable(), resource: z.string().url().nullable(), protectedResourceMetadataUrl: z.string().url().nullable(), authorizationServerMetadataUrl: z.string().url().nullable(), authorizationEndpoint: z.string().url().nullable(), tokenEndpoint: z.string().url().nullable(), revocationEndpoint: z.string().url().nullable(),
15
+ authorizationMode: z.literal('OAUTH_2_1_AUTHORIZATION_CODE_PKCE_S256_USER_DELEGATED'), clientRegistration: z.literal('PRE_REGISTERED'), clientId: z.null(), authorizationMapping: z.object({ oauthResourceParameter: z.literal('resource'), externalTenantParameter: z.literal('external_tenant_id'), projectRefParameter: z.literal('project_ref'), externalSystemSource: z.literal('client_id'), grantBinding: z.literal('RESOURCE_EXTERNAL_TENANT_PROJECT_REF_SCOPES') }).strict(), searchCoverage: z.enum(['AUTHORIZED_METADATA_V1', 'AUTHORIZED_PRESENTATION_V1']),
16
+ scopes: z.array(knowledgeMcpScopeSchema).length(3), tools: z.array(z.object({ name: knowledgeMcpToolNameSchema, requiredScope: knowledgeMcpScopeSchema, inputSchema: z.json() }).strict()).length(4),
17
+ }).strict();
18
+ /** 版本化元数据只声明实际启用的协议;保留严格 v1,避免旧消费者误认新增生命周期。 */
19
+ const providerV2BaseSchema = knowledgeMcpProviderContractSchema.omit({ schemaVersion: true, protocolVersion: true }).extend({
20
+ schemaVersion: z.literal(2), defaultProtocolVersion: z.literal(knowledgeMcpProtocolVersion),
21
+ protocols: z.array(z.discriminatedUnion('version', [
22
+ z.object({ version: z.literal('2026-07-28'), lifecycle: z.literal('STATELESS_DISCOVERY'), transport: z.literal('STREAMABLE_HTTP') }).strict(),
23
+ z.object({ version: z.literal('2025-06-18'), lifecycle: z.literal('INITIALIZE'), transport: z.literal('STREAMABLE_HTTP') }).strict(),
24
+ ])).min(1).max(2),
25
+ }).strict();
26
+ export const knowledgeMcpProviderContractV2Schema = providerV2BaseSchema.superRefine((value, ctx) => {
27
+ const versions = value.protocols.map(p => p.version);
28
+ if (new Set(versions).size !== versions.length || !versions.includes(value.defaultProtocolVersion))
29
+ ctx.addIssue({ code: 'custom', message: 'Protocols must be unique and include the default version' });
30
+ });
31
+ /** v3 区分原始 Evidence 文件和受治理正文端点,旧 provider 合同仍保持原样。 */
32
+ export const knowledgeMcpProviderContractV3Schema = providerV2BaseSchema.omit({ schemaVersion: true, tools: true }).extend({
33
+ schemaVersion: z.literal(3), contentEndpoint: z.string().url().nullable(), evidenceFileEndpoint: z.string().url().nullable(),
34
+ tools: z.array(z.object({ name: knowledgeMcpToolNameV2Schema, requiredScope: knowledgeMcpScopeSchema, inputSchema: z.json() }).strict()).length(5),
35
+ }).strict().superRefine((value, ctx) => {
36
+ const versions = value.protocols.map(p => p.version);
37
+ if (new Set(versions).size !== versions.length || !versions.includes(value.defaultProtocolVersion))
38
+ ctx.addIssue({ code: 'custom', message: 'Protocols must be unique and include the default version' });
39
+ });
40
+ // 五个工具的成功结构直接取通用消费 DTO;失败只返回错误码,不泄露被拒绝正文。
41
+ const toolErrorOutput = { type: 'object', properties: { errorCode: { type: 'string' } }, required: ['errorCode'], additionalProperties: false };
42
+ const toolOutput = (success) => ({ type: 'object', oneOf: [z.toJSONSchema(success, { target: 'draft-07' }), toolErrorOutput] });
43
+ export const knowledgeMaterialListInputSchema = z.object({ projectRef: consumerProjectRefSchema, after: stableUriSchema.optional(), limit: z.number().int().min(1).max(20).optional(), resourceType: materialResourceTypeSchema.optional(), sourceProjectKey: projectKeySchema.optional(), refPrefix: z.string().regex(/^[a-z][a-z0-9+.-]*:\/\/[!-~]*$/i).max(256).optional() }).strict();
44
+ export const knowledgeMaterialRefInputSchema = z.object({ projectRef: consumerProjectRefSchema, ref: stableUriSchema }).strict();
45
+ export const knowledgeMaterialWindowInputSchema = z.object({ projectRef: consumerProjectRefSchema }).strict();
46
+ export const knowledgeMaterialWindowResponseSchema = materialOutboxWindowSchema.safeExtend({ projectRef: consumerProjectRefSchema });
47
+ export const knowledgeMaterialChangesInputSchema = z.object({ projectRef: consumerProjectRefSchema, afterSeq: z.number().int().nonnegative().safe().optional(), limit: z.number().int().min(1).max(20).optional() }).strict();
48
+ export const knowledgeMaterialSearchInputSchema = z.object({ projectRef: consumerProjectRefSchema, query: z.string().min(2).max(200), afterId: z.number().int().nonnegative().safe().optional(), limit: z.number().int().min(1).max(20).optional(), resourceType: materialResourceTypeSchema.optional(), sourceProjectKey: projectKeySchema.optional() }).strict();
49
+ export const knowledgeMaterialPartitionsInputSchema = z.object({ projectRef: consumerProjectRefSchema, afterRouteId: z.string().regex(/^[a-f0-9]{64}$/).optional(), limit: z.number().int().min(1).max(20).optional() }).strict();
50
+ export const knowledgeMaterialPartitionPageInputSchema = z.object({ projectRef: consumerProjectRefSchema, partition: z.enum(['OWNER', 'LEGACY']), after: stableUriSchema.optional(), limit: z.number().int().min(1).max(20).optional() }).strict();
51
+ export const knowledgeMaterialRoutePageInputSchema = z.object({ projectRef: consumerProjectRefSchema, routeId: z.string().regex(/^[a-f0-9]{64}$/), after: stableUriSchema.optional(), limit: z.number().int().min(1).max(20).optional() }).strict();
52
+ export const knowledgeMaterialMediaInputSchema = knowledgeMaterialRefInputSchema.extend({ afterOrdinal: z.number().int().min(-1).safe().optional(), limit: z.number().int().min(1).max(20).optional(), documentRef: stableUriSchema.optional() }).strict();
53
+ export const knowledgeMaterialIndexStatusInputSchema = z.object({ projectRef: consumerProjectRefSchema, afterSourceKey: projectKeySchema.optional(), afterNodeId: z.string().min(1).max(128).optional(), sourceProjectKey: projectKeySchema.optional(), limit: z.number().int().min(1).max(20).optional() }).strict();
54
+ export const knowledgeMaterialCapabilitiesResponseSchema = materialCapabilityResponseSchema.omit({ projectKey: true }).extend({ projectRef: consumerProjectRefSchema, downloadUrl: z.string().url() }).strict();
55
+ export const knowledgeMaterialMediaResponseSchema = materialMediaCapabilityPageSchema.omit({ projectKey: true }).extend({ projectRef: consumerProjectRefSchema }).strict();
56
+ export const knowledgeMaterialIndexStatusResponseSchema = materialIndexStatusSchema.omit({ projectKey: true }).extend({ projectRef: consumerProjectRefSchema }).strict();
57
+ export const knowledgeMaterialToolInputSchemas = {
58
+ knowledge_material_capabilities: z.toJSONSchema(knowledgeMaterialRefInputSchema, { target: 'draft-07' }),
59
+ knowledge_material_media: z.toJSONSchema(knowledgeMaterialMediaInputSchema, { target: 'draft-07' }),
60
+ knowledge_material_index_status: z.toJSONSchema(knowledgeMaterialIndexStatusInputSchema, { target: 'draft-07' }),
61
+ knowledge_material_window: z.toJSONSchema(knowledgeMaterialWindowInputSchema, { target: 'draft-07' }),
62
+ knowledge_material_list: z.toJSONSchema(knowledgeMaterialListInputSchema, { target: 'draft-07' }),
63
+ knowledge_material_describe: z.toJSONSchema(knowledgeMaterialRefInputSchema, { target: 'draft-07' }),
64
+ knowledge_material_read: z.toJSONSchema(knowledgeMaterialRefInputSchema, { target: 'draft-07' }),
65
+ knowledge_material_changes: z.toJSONSchema(knowledgeMaterialChangesInputSchema, { target: 'draft-07' }),
66
+ knowledge_material_search: z.toJSONSchema(knowledgeMaterialSearchInputSchema, { target: 'draft-07' }),
67
+ knowledge_material_partitions: z.toJSONSchema(knowledgeMaterialPartitionsInputSchema, { target: 'draft-07' }),
68
+ knowledge_material_partition_page: z.toJSONSchema(knowledgeMaterialPartitionPageInputSchema, { target: 'draft-07' }),
69
+ knowledge_material_route_page: z.toJSONSchema(knowledgeMaterialRoutePageInputSchema, { target: 'draft-07' }),
70
+ };
71
+ export const knowledgeMaterialListResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, contentClass: z.literal('MATERIAL_DIRECTORY'), queryCoverage: z.literal('INDEXED_REF_SOURCE_TYPE_V1'), order: z.literal('REF_ASC'), items: z.array(servingMaterialDirectoryItemSchema).max(20), nextAfter: stableUriSchema.nullable() }).strict();
72
+ export const knowledgeMaterialDescribeResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, contentClass: z.literal('MATERIAL_DESCRIPTOR'), item: servingMaterialDirectoryItemSchema, metadataByteLength: z.number().int().nonnegative().nullable(), downloadUrl: z.string().url() }).strict();
73
+ export const knowledgeMaterialReadResponseSchema = knowledgeMaterialDescribeResponseSchema.omit({ contentClass: true }).extend({ contentClass: z.literal('MATERIAL_READ'), inlineComplete: z.boolean(), byteVerification: z.enum(['VERIFIED', 'ON_DOWNLOAD']), contentBase64: z.string().nullable(), fileDescriptor: z.object({ contentHash: sha256Schema, mediaType: z.string().min(1).max(256), byteLength: z.number().int().nonnegative() }).strict().nullable() }).strict();
74
+ export const knowledgeMaterialChangesResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, tenantId: z.string().min(1), items: z.array(z.object({ seq: z.number().int().positive(), eventType: z.enum(['MATERIAL_REGISTERED', 'MATERIAL_LINEAGE_CHANGED', 'ROUTE_CHANGED', 'PROJECT_SCOPE_CHANGED']), artifactRef: stableUriSchema.nullable(), contentHash: sha256Schema.nullable(), routeId: z.string().nullable(), createdAt: z.string().datetime({ offset: true }) }).strict()).max(20), nextAfter: z.number().int().positive().nullable() }).strict();
75
+ export const knowledgeMaterialSearchResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, queryCoverage: z.literal('DESCRIPTIVE_METADATA_V1'), order: z.literal('INDEX_ROWID_ASC'), indexState: z.enum(['PARTIAL_BACKFILL', 'SYNCED_AS_OF_LAST_OBSERVATION']), configuredSourceCount: z.number().int().nonnegative(), items: z.array(z.object({ item: servingMaterialDirectoryItemSchema, title: z.string().max(512), summary: z.string().max(1024) }).strict()).max(20), nextAfterId: z.number().int().positive().nullable() }).strict();
76
+ export const oauthMaterialRoutePageResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, projectKey: projectKeySchema, routeId: z.string().regex(/^[a-f0-9]{64}$/), contentClass: z.literal('MATERIAL_DIRECTORY'), routeState: z.enum(['ACTIVE', 'REVOKED', 'UNBOUND']), items: z.array(servingMaterialDirectoryItemSchema).max(100), nextAfter: stableUriSchema.nullable() }).strict();
77
+ export const oauthMaterialPartitionsResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, projectKey: projectKeySchema, coverage: z.literal('OWNER_LEGACY_AND_ACTIVE_ROUTES'), items: z.array(materialRoutePartitionSchema).max(100), nextAfterRouteId: z.string().regex(/^[a-f0-9]{64}$/).nullable() }).strict();
78
+ export const oauthMaterialPartitionPageResponseSchema = z.object({ schemaVersion: schemaVersionSchema, projectRef: consumerProjectRefSchema, projectKey: projectKeySchema, contentClass: z.literal('MATERIAL_DIRECTORY'), partition: z.enum(['OWNER', 'LEGACY']), items: z.array(servingMaterialDirectoryItemSchema).max(100), nextAfter: stableUriSchema.nullable() }).strict();
79
+ export const knowledgeMaterialPartitionsResponseSchema = oauthMaterialPartitionsResponseSchema.extend({ items: z.array(materialRoutePartitionSchema).max(20) }).omit({ projectKey: true }).strict();
80
+ export const knowledgeMaterialPartitionPageResponseSchema = oauthMaterialPartitionPageResponseSchema.extend({ items: z.array(servingMaterialDirectoryItemSchema).max(20) }).omit({ projectKey: true }).strict();
81
+ export const knowledgeMaterialRoutePageResponseSchema = oauthMaterialRoutePageResponseSchema.extend({ items: z.array(servingMaterialDirectoryItemSchema).max(20) }).omit({ projectKey: true }).strict();
82
+ export const knowledgeMcpToolOutputSchemas = {
83
+ knowledge_material_capabilities: toolOutput(knowledgeMaterialCapabilitiesResponseSchema),
84
+ knowledge_material_media: toolOutput(knowledgeMaterialMediaResponseSchema),
85
+ knowledge_material_index_status: toolOutput(knowledgeMaterialIndexStatusResponseSchema),
86
+ knowledge_material_window: toolOutput(knowledgeMaterialWindowResponseSchema),
87
+ knowledge_search: toolOutput(consumerSearchResponseSchema),
88
+ knowledge_read: toolOutput(consumerReadResponseSchema),
89
+ knowledge_list_evidence: toolOutput(consumerEvidencePageResponseSchema),
90
+ knowledge_currentness: toolOutput(consumerCurrentnessResponseSchema),
91
+ knowledge_reference_lookup: toolOutput(consumerReferenceLookupResponseSchema),
92
+ knowledge_material_list: toolOutput(knowledgeMaterialListResponseSchema),
93
+ knowledge_material_describe: toolOutput(knowledgeMaterialDescribeResponseSchema),
94
+ knowledge_material_read: toolOutput(knowledgeMaterialReadResponseSchema),
95
+ knowledge_material_changes: toolOutput(knowledgeMaterialChangesResponseSchema),
96
+ knowledge_material_search: toolOutput(knowledgeMaterialSearchResponseSchema),
97
+ knowledge_material_partitions: toolOutput(knowledgeMaterialPartitionsResponseSchema),
98
+ knowledge_material_partition_page: toolOutput(knowledgeMaterialPartitionPageResponseSchema),
99
+ knowledge_material_route_page: toolOutput(knowledgeMaterialRoutePageResponseSchema),
100
+ };
101
+ /** v4 在独立发现版本中公布工具输出合同,v1 至 v3 的严格结构不变。 */
102
+ export const knowledgeMcpProviderContractV4Schema = providerV2BaseSchema.omit({ schemaVersion: true, tools: true }).extend({
103
+ schemaVersion: z.literal(4), contentEndpoint: z.string().url().nullable(), evidenceFileEndpoint: z.string().url().nullable(),
104
+ tools: z.array(z.object({ name: knowledgeMcpToolNameV2Schema, requiredScope: knowledgeMcpScopeSchema, inputSchema: z.json(), outputSchema: z.json() }).strict()).length(5),
105
+ }).strict().superRefine((value, ctx) => {
106
+ const versions = value.protocols.map(p => p.version);
107
+ if (new Set(versions).size !== versions.length || !versions.includes(value.defaultProtocolVersion))
108
+ ctx.addIssue({ code: 'custom', message: 'Protocols must be unique and include the default version' });
109
+ });
110
+ /** v5 单独声明受治理写入工具;旧版本继续只描述只读消费合同。 */
111
+ export const knowledgeMcpProviderContractV5Schema = providerV2BaseSchema.omit({ schemaVersion: true, tools: true, scopes: true }).extend({
112
+ schemaVersion: z.literal(5), contentEndpoint: z.string().url().nullable(), evidenceFileEndpoint: z.string().url().nullable(), managementMode: z.literal('EXPLICIT_CLIENT_PROJECT_SCOPE'), managementEnabled: z.boolean(),
113
+ scopes: z.array(z.enum(['knowledge.search', 'knowledge.read', 'knowledge.currentness', 'knowledge.compose', 'knowledge.review', 'knowledge.approve'])).min(3).max(6),
114
+ tools: z.array(z.object({ name: z.enum(['knowledge_search', 'knowledge_read', 'knowledge_currentness', 'knowledge_reference_lookup', 'knowledge_list_evidence', 'knowledge_compose', 'knowledge_submit_review', 'knowledge_review', 'knowledge_finalize_review']), requiredScope: z.enum(['knowledge.search', 'knowledge.read', 'knowledge.currentness', 'knowledge.compose', 'knowledge.review', 'knowledge.approve']), inputSchema: z.json(), outputSchema: z.json() }).strict()).min(5).max(9),
115
+ }).strict();
116
+ /** v6 advertises tenant-scoped, immutable material discovery and byte reads. */
117
+ export const knowledgeMcpProviderContractV6Schema = knowledgeMcpProviderContractV5Schema.omit({ schemaVersion: true }).extend({ schemaVersion: z.literal(6), materialPageEndpoint: z.string().url(), materialEndpoint: z.string().url(), materialPresentationEndpoint: z.string().url() }).strict();
118
+ /** v7 publishes independent raw-material consent without changing older provider contracts. */
119
+ export const knowledgeMcpProviderContractV7Schema = knowledgeMcpProviderContractV6Schema.omit({ schemaVersion: true, scopes: true, tools: true }).extend({
120
+ schemaVersion: z.literal(7), materialReadMode: z.literal('OAUTH_SCOPE_AND_CLIENT_PROJECT_BINDING'),
121
+ scopes: z.array(z.enum(['knowledge.search', 'knowledge.read', 'knowledge.currentness', 'knowledge.material.read', 'knowledge.compose', 'knowledge.review', 'knowledge.approve', 'knowledge.material.route'])).min(4).max(8),
122
+ tools: z.array(z.object({ name: z.enum(['knowledge_search', 'knowledge_read', 'knowledge_currentness', 'knowledge_reference_lookup', 'knowledge_list_evidence', 'knowledge_material_list', 'knowledge_material_describe', 'knowledge_material_read', 'knowledge_material_changes', 'knowledge_compose', 'knowledge_submit_review', 'knowledge_review', 'knowledge_finalize_review', 'knowledge_material_route']), requiredScope: z.enum(['knowledge.search', 'knowledge.read', 'knowledge.currentness', 'knowledge.material.read', 'knowledge.compose', 'knowledge.review', 'knowledge.approve', 'knowledge.material.route']), inputSchema: z.json(), outputSchema: z.json() }).strict()).min(9).max(14),
123
+ }).strict();
124
+ /** v8 adds descriptive metadata search with an explicit index-coverage state. */
125
+ export const knowledgeMcpProviderContractV8Schema = knowledgeMcpProviderContractV7Schema.omit({ schemaVersion: true, tools: true }).extend({
126
+ schemaVersion: z.literal(8), materialSearchMode: z.literal('INDEXED_DESCRIPTIVE_METADATA'), materialSearchEndpoint: z.string().url(),
127
+ tools: z.array(z.object({ name: z.enum(['knowledge_search', 'knowledge_read', 'knowledge_currentness', 'knowledge_reference_lookup', 'knowledge_list_evidence', 'knowledge_material_list', 'knowledge_material_describe', 'knowledge_material_read', 'knowledge_material_changes', 'knowledge_material_search', 'knowledge_compose', 'knowledge_submit_review', 'knowledge_review', 'knowledge_finalize_review', 'knowledge_material_route']), requiredScope: z.enum(['knowledge.search', 'knowledge.read', 'knowledge.currentness', 'knowledge.material.read', 'knowledge.compose', 'knowledge.review', 'knowledge.approve', 'knowledge.material.route']), inputSchema: z.json(), outputSchema: z.json() }).strict()).min(10).max(15),
128
+ }).strict();
129
+ /** v9 advertises bounded per-route replay for null-ref change events. */
130
+ export const knowledgeMcpProviderContractV9Schema = knowledgeMcpProviderContractV8Schema.omit({ schemaVersion: true }).extend({ schemaVersion: z.literal(9), materialRoutePageEndpoint: z.string().url() }).strict();
131
+ /** v10 publishes route-count-independent partitioned material discovery. */
132
+ export const knowledgeMcpProviderContractV10Schema = knowledgeMcpProviderContractV9Schema.omit({ schemaVersion: true, tools: true }).extend({ schemaVersion: z.literal(10), materialPartitionsEndpoint: z.string().url(), materialPartitionPageEndpoint: z.string().url(), tools: z.array(z.object({ name: z.enum(['knowledge_search', 'knowledge_read', 'knowledge_currentness', 'knowledge_reference_lookup', 'knowledge_list_evidence', 'knowledge_material_list', 'knowledge_material_describe', 'knowledge_material_read', 'knowledge_material_changes', 'knowledge_material_search', 'knowledge_material_partitions', 'knowledge_material_partition_page', 'knowledge_material_route_page', 'knowledge_compose', 'knowledge_submit_review', 'knowledge_review', 'knowledge_finalize_review', 'knowledge_material_route']), requiredScope: z.enum(['knowledge.search', 'knowledge.read', 'knowledge.currentness', 'knowledge.material.read', 'knowledge.compose', 'knowledge.review', 'knowledge.approve', 'knowledge.material.route']), inputSchema: z.json(), outputSchema: z.json() }).strict()).min(13).max(18) }).strict();
133
+ /** v11 adds an Agent-native checkpoint for initial synchronization and retention-gap recovery. */
134
+ export const knowledgeMcpProviderContractV11Schema = knowledgeMcpProviderContractV10Schema.omit({ schemaVersion: true, tools: true }).extend({ schemaVersion: z.literal(11), materialOutboxWindowEndpoint: z.string().url(), tools: z.array(knowledgeMcpProviderContractV10Schema.shape.tools.element.extend({ name: knowledgeMcpProviderContractV10Schema.shape.tools.element.shape.name.or(z.literal('knowledge_material_window')) })).min(14).max(19) }).strict();
135
+ /** v12 exposes representation capabilities independently of raw authorization and search coverage. */
136
+ export const knowledgeMcpProviderContractV12Schema = knowledgeMcpProviderContractV11Schema.omit({ schemaVersion: true, tools: true }).extend({ schemaVersion: z.literal(12), materialCapabilitySchemaVersion: z.literal(2), materialCapabilitiesEndpoint: z.string().url(), materialCapabilityPageEndpoint: z.string().url(), materialMediaPageEndpoint: z.string().url(), materialIndexStatusEndpoint: z.string().url(), tools: z.array(knowledgeMcpProviderContractV11Schema.shape.tools.element.extend({ name: knowledgeMcpProviderContractV11Schema.shape.tools.element.shape.name.or(z.enum(['knowledge_material_capabilities', 'knowledge_material_media', 'knowledge_material_index_status'])) })).min(17).max(22) }).strict();
137
+ /** v13 adds explicit material production; older versions keep their scope and tool enums. */
138
+ export const knowledgeMcpProviderContractV13Schema = knowledgeMcpProviderContractV12Schema.omit({ schemaVersion: true, tools: true, scopes: true }).extend({ schemaVersion: z.literal(13), scopes: z.array(knowledgeMcpProviderContractV12Schema.shape.scopes.element.or(z.literal('knowledge.material.write'))).min(4).max(9), tools: z.array(knowledgeMcpProviderContractV12Schema.shape.tools.element.extend({ name: knowledgeMcpProviderContractV12Schema.shape.tools.element.shape.name.or(z.literal('knowledge_material_register')), requiredScope: knowledgeMcpProviderContractV12Schema.shape.tools.element.shape.requiredScope.or(z.literal('knowledge.material.write')) })).min(17).max(23), materialRegistration: z.object({ maxInlineBytes: z.literal(65536), retry: z.literal('EXACT_IMMUTABLE_REF'), phases: z.tuple([z.literal('PERSISTED'), z.literal('CATALOG_PROJECTED'), z.literal('REGISTERED')]) }).strict() }).strict();
139
+ /** v15 才扩展 Agent 治理工具和 scope;v1–v14 的严格枚举保持原样。 */
140
+ export const knowledgeMcpProviderContractV15Schema = knowledgeMcpProviderContractV13Schema.omit({ schemaVersion: true, tools: true, scopes: true }).extend({ schemaVersion: z.literal(15), workflowSchemaVersion: z.literal(1), managementEndpoint: z.string().url(), scopes: z.array(knowledgeMcpProviderContractV13Schema.shape.scopes.element.or(z.literal('knowledge.workflow.read'))).min(4).max(10), tools: z.array(knowledgeMcpProviderContractV13Schema.shape.tools.element.extend({ name: knowledgeMcpProviderContractV13Schema.shape.tools.element.shape.name.or(z.enum(['knowledge_workflow_guide', 'knowledge_workflow_plan', 'knowledge_workflow_advance', 'knowledge_agent_submit'])), requiredScope: knowledgeMcpProviderContractV13Schema.shape.tools.element.shape.requiredScope.or(z.literal('knowledge.workflow.read')) })).min(17).max(27) }).strict();
@@ -0,0 +1,13 @@
1
+ /** 显式 native consumer;旧 profile/Provider/Workflow schema 1 不自动升级。 */
2
+ import { z } from 'zod';
3
+ import { tenantResourceRefSchema, tenantManagementRequestIdSchema, materialTenantIdSchema, artifactStatusSchema, sha256Schema, tenantMaterialCurrentnessSchema, tenantPublicationReadinessSchema } from '../contracts/index.js';
4
+ import { consumerProfileSchema, servingDecisionSchema } from './core.js';
5
+ export const tenantConsumerProfileSchema = z.object({ ...consumerProfileSchema.shape, schemaVersion: z.literal(2), acceptedCurrentnessBases: z.array(z.literal('RETAINED_SNAPSHOT')).max(1), legacySourcePolicy: z.literal('PROJECT_POLICY_V1').optional() }).strict().superRefine((v, ctx) => { const { acceptedCurrentnessBases, legacySourcePolicy, schemaVersion, ...base } = v, checked = consumerProfileSchema.safeParse({ ...base, schemaVersion: 1 }); if (!checked.success)
6
+ for (const issue of checked.error.issues)
7
+ ctx.addIssue({ code: 'custom', path: issue.path, message: issue.message }); if (new Set(v.acceptedCurrentnessBases).size !== v.acceptedCurrentnessBases.length)
8
+ ctx.addIssue({ code: 'custom', message: 'currentness bases must be unique' }); });
9
+ const readDecision = z.object({ action: z.enum(['ALLOW', 'REVIEW_REQUIRED', 'DENY']), reasonCodes: z.array(z.string()).max(32), authority: z.enum(['AUTHENTICATED_READER', 'LOCAL_PROFILE_SIMULATION']) }).strict();
10
+ export const tenantWorkflowPlanInputSchema = z.object({ ref: tenantResourceRefSchema }).strict();
11
+ export const tenantWorkflowAdvanceInputSchema = z.object({ requestId: tenantManagementRequestIdSchema, ref: tenantResourceRefSchema, expectedVersion: z.number().int().positive().safe(), action: z.enum(['SUBMIT_REVIEW', 'FINALIZE_REVIEW']), reviewRef: tenantResourceRefSchema.optional() }).strict();
12
+ export const tenantWorkflowPlanSchema = z.object({ schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, ref: tenantResourceRefSchema, contentHash: sha256Schema, resourceType: z.string(), kind: z.string(), version: z.number().int().positive(), status: artifactStatusSchema.or(z.enum(['RAW_MATERIAL', 'RAW_EVIDENCE', 'REFERENCE_SNAPSHOT', 'REGISTERED_MATERIAL'])), productionPhase: z.literal('REGISTERED'), readiness: tenantPublicationReadinessSchema.nullable(), currentness: tenantMaterialCurrentnessSchema.nullable(), governedPolicyReady: z.boolean(), consumerReadDecision: readDecision.nullable(), externalReady: z.boolean(), successorRef: tenantResourceRefSchema.nullable(), blockers: z.array(z.string()).max(64), nextActions: z.array(z.object({ id: z.string(), tool: z.string().nullable(), arguments: z.record(z.string(), z.json()), requiredScopes: z.array(z.string()), missingScopes: z.array(z.string()), missingFields: z.array(z.string()), canExecute: z.boolean(), automatic: z.boolean(), reasonCode: z.string() }).strict()).max(16) }).strict();
13
+ export const tenantGovernedReadResultSchema = z.object({ schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, ref: tenantResourceRefSchema, decision: servingDecisionSchema, descriptor: z.object({ contentHash: sha256Schema, mediaType: z.string(), byteLength: z.number().int().nonnegative() }).strict().nullable() }).strict();
@@ -0,0 +1,89 @@
1
+ /** 新 Tenant 管理工具共同合同;认证 context/actor/authority 只由 adapter 注入。 */
2
+ import { z } from 'zod';
3
+ import { parseTenantResourceRef, tenantStorageKey, tenantRawSubmissionSchema, tenantArtifactDraftSchema, tenantComposeInputSchema, tenantReviewInputSchema, tenantPromoteInputSchema, tenantSnapshotInputSchema, tenantShareInputSchema, tenantRevokeShareInputSchema, tenantResourceManifestSchema, tenantMaterialCurrentnessSchema, tenantSourceSemanticsSchema, tenantSourceIdSchema, tenantSourceSnapshotSchema, collectionRefreshSchema, tenantCollectionCycleSchema, tenantCollectionRequestSchema, tenantCollectionBatchSchema, tenantCollectionCompletionSchema, tenantCollectionFailureSchema, tenantResourceRefSchema, materialTenantIdSchema, sha256Schema, isoDateTimeSchema, stableUriSchema } from '../contracts/index.js';
4
+ import { tenantWorkflowPlanSchema, tenantWorkflowPlanInputSchema, tenantWorkflowAdvanceInputSchema, tenantGovernedReadResultSchema } from './tenant-governance.js';
5
+ const base64 = z.string().min(4).max(87384).regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/), ref = z.object({ ref: tenantResourceRefSchema }).strict(), page = z.object({ after: z.string().min(1).max(128).optional(), limit: z.number().int().min(1).max(100).optional() }).strict(), source = z.object({ sourceId: tenantSourceIdSchema }).strict();
6
+ export const tenantManagementToolSchemas = {
7
+ tenant_material_submit: tenantRawSubmissionSchema.extend({ contentBase64: base64 }).strict(),
8
+ tenant_artifact_draft: tenantArtifactDraftSchema.extend({ contentBase64: base64 }).strict(),
9
+ tenant_knowledge_compose: tenantComposeInputSchema,
10
+ tenant_knowledge_review: tenantReviewInputSchema,
11
+ tenant_artifact_promote: tenantPromoteInputSchema,
12
+ tenant_snapshot_declare: tenantSnapshotInputSchema,
13
+ tenant_snapshot_status: ref,
14
+ tenant_material_share: tenantShareInputSchema,
15
+ tenant_material_revoke: tenantRevokeShareInputSchema,
16
+ tenant_material_routes: page,
17
+ tenant_workflow_guide: z.object({}).strict(),
18
+ tenant_workflow_plan: tenantWorkflowPlanInputSchema,
19
+ tenant_workflow_advance: tenantWorkflowAdvanceInputSchema,
20
+ tenant_knowledge_read: ref,
21
+ tenant_source_define: z.object({ definition: z.object({ schemaVersion: z.literal(1), sourceId: tenantSourceIdSchema, title: z.string().trim().min(1).max(512), semantics: tenantSourceSemanticsSchema }).strict(), expectedGeneration: z.number().int().positive().safe().nullable() }).strict(),
22
+ tenant_source_configure: source.extend({ expectedGeneration: z.number().int().positive().safe(), paused: z.boolean(), tenantEnabled: z.boolean(), refresh: collectionRefreshSchema }).strict(),
23
+ tenant_source_get: source,
24
+ tenant_source_list: page,
25
+ tenant_collection_request: z.object({ requestId: tenantCollectionCycleSchema, sourceId: tenantSourceIdSchema, expectedSourceRevisionRef: stableUriSchema.optional(), cycleId: tenantCollectionCycleSchema.optional() }).strict(),
26
+ tenant_collection_status: z.object({ requestId: tenantCollectionCycleSchema }).strict(),
27
+ };
28
+ /** 固定能力索引;promote/advance 的调用鉴权必须使用 scopesForInput,发现使用 Authorization。 */
29
+ export const tenantManagementToolScopes = { tenant_material_submit: 'knowledge.material.write', tenant_artifact_draft: 'knowledge.material.write', tenant_knowledge_compose: 'knowledge.compose', tenant_knowledge_review: 'knowledge.review', tenant_artifact_promote: 'knowledge.material.write', tenant_snapshot_declare: 'knowledge.review', tenant_snapshot_status: 'knowledge.workflow.read', tenant_material_share: 'knowledge.material.route', tenant_material_revoke: 'knowledge.material.route', tenant_material_routes: 'knowledge.material.route', tenant_workflow_guide: 'knowledge.workflow.read', tenant_workflow_plan: 'knowledge.workflow.read', tenant_workflow_advance: 'knowledge.workflow.read', tenant_knowledge_read: 'knowledge.read', tenant_source_define: 'knowledge.source.manage', tenant_source_configure: 'knowledge.source.manage', tenant_source_get: 'knowledge.source.manage', tenant_source_list: 'knowledge.source.manage', tenant_collection_request: 'knowledge.collect', tenant_collection_status: 'knowledge.collect' };
30
+ /** 初始动作能力来自同一输入合同;依赖原件读取等附加检查仍在 application。 */
31
+ export function tenantManagementScopesForInput(name, raw) {
32
+ const input = tenantManagementToolSchemas[name].parse(raw);
33
+ if (name === 'tenant_artifact_promote')
34
+ return [tenantPromoteInputSchema.parse(input).nextStatus === 'READY_FOR_REVIEW' ? 'knowledge.material.write' : 'knowledge.approve'];
35
+ if (name === 'tenant_workflow_advance')
36
+ return ['knowledge.workflow.read', tenantWorkflowAdvanceInputSchema.parse(input).action === 'SUBMIT_REVIEW' ? 'knowledge.material.write' : 'knowledge.approve'];
37
+ return [tenantManagementToolScopes[name]];
38
+ }
39
+ export function tenantManagementAuthorization(name) {
40
+ if (name === 'tenant_artifact_promote')
41
+ return { selection: 'NEXT_STATUS', scopeAlternatives: [['knowledge.material.write'], ['knowledge.approve']] };
42
+ if (name === 'tenant_workflow_advance')
43
+ return { selection: 'WORKFLOW_ACTION', scopeAlternatives: [['knowledge.workflow.read', 'knowledge.material.write'], ['knowledge.workflow.read', 'knowledge.approve']] };
44
+ return { selection: 'FIXED', scopeAlternatives: [[tenantManagementToolScopes[name]]] };
45
+ }
46
+ // advance/promote 的实际动作、来源/审核读取能力继续由 application/context 逐项复核。
47
+ const production = z.object({ phase: z.literal('REGISTERED'), ref: tenantResourceRefSchema, registered: z.boolean(), seq: z.number().int().positive(), manifestRevision: sha256Schema }).strict();
48
+ const write = z.object({ inserted: z.boolean(), manifest: tenantResourceManifestSchema, production }).strict();
49
+ const projection = z.object({ changed: z.boolean(), seq: z.number().int().positive(), assessmentRevision: sha256Schema }).strict();
50
+ const route = z.object({ routeId: z.string().regex(/^[a-f0-9]{64}$/), ownerTenantId: materialTenantIdSchema, recipientTenantId: materialTenantIdSchema, sourceProjectKey: z.null(), matchType: z.enum(['SOURCE', 'REF']), matchValue: stableUriSchema, effect: z.enum(['ALLOW', 'DENY']), revokedAt: isoDateTimeSchema.nullable() }).strict();
51
+ const routeChange = z.object({ changed: z.boolean(), route, completedPhase: z.literal('ROUTE_COMMITTED'), operationRef: stableUriSchema }).strict();
52
+ const sourceHead = z.object({ tenantId: materialTenantIdSchema, sourceId: tenantSourceIdSchema, revisionRef: stableUriSchema, semanticKey: sha256Schema, generation: z.number().int().positive().safe(), paused: z.boolean(), tenantEnabled: z.boolean(), refresh: collectionRefreshSchema, snapshot: tenantSourceSnapshotSchema }).strict().superRefine((v, ctx) => { if (v.tenantId !== v.snapshot.tenantId || v.sourceId !== v.snapshot.sourceId || v.revisionRef !== v.snapshot.revisionRef || v.semanticKey !== v.snapshot.semanticKey)
53
+ ctx.addIssue({ code: 'custom', message: 'Source head preserves its exact snapshot identity' }); });
54
+ const governedRead = tenantGovernedReadResultSchema.extend({ contentBase64: base64.max(43692).nullable(), truncated: z.boolean(), continuation: z.object({ kind: z.literal('AUTHENTICATED_TENANT_GOVERNED_CONTENT'), ref: tenantResourceRefSchema }).strict().nullable() }).strict().superRefine((v, ctx) => {
55
+ const length = v.contentBase64 === null ? 0 : v.contentBase64.length / 4 * 3 - (v.contentBase64.endsWith('==') ? 2 : v.contentBase64.endsWith('=') ? 1 : 0);
56
+ if (v.decision.action === 'ALLOW' ? (!v.descriptor || v.contentBase64 === null || length > 32768 || (v.truncated ? (!v.continuation || v.continuation.ref !== v.ref || v.descriptor.byteLength <= length) : (v.continuation !== null || v.descriptor.byteLength !== length))) : (v.descriptor !== null || v.contentBase64 !== null || v.truncated || v.continuation !== null))
57
+ ctx.addIssue({ code: 'custom', message: 'Governed inline data and continuation must match the actual content decision and full length' });
58
+ });
59
+ const guide = z.object({ schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, authorityVersion: z.literal(2), scopes: z.array(z.string()).max(32), tools: z.array(z.object({ name: z.string(), authorization: z.object({ selection: z.enum(['FIXED', 'NEXT_STATUS', 'WORKFLOW_ACTION']), scopeAlternatives: z.array(z.array(z.string()).min(1).max(8)).min(1).max(4) }).strict(), inputSchema: z.json(), outputSchema: z.json() }).strict()).max(64), rules: z.array(z.string()).max(32), limits: z.object({ requestMaxBytes: z.literal(131072), resultMaxBytes: z.literal(524288), submissionMaxBytes: z.literal(65536) }).strict() }).strict();
60
+ export const tenantManagementDataSchemas = {
61
+ tenant_material_submit: write, tenant_artifact_draft: write, tenant_knowledge_compose: write, tenant_knowledge_review: write, tenant_artifact_promote: write,
62
+ tenant_snapshot_declare: z.object({ subjectRef: tenantResourceRefSchema, declared: z.boolean(), declarationRef: stableUriSchema, assessment: tenantMaterialCurrentnessSchema, projection, completedPhase: z.literal('CURRENTNESS_NOTIFIED'), operationRef: stableUriSchema }).strict(),
63
+ tenant_snapshot_status: z.object({ subjectRef: tenantResourceRefSchema, state: z.enum(['NOT_AVAILABLE', 'NOT_DECLARED', 'PROJECTION_PENDING', 'READY', 'INTEGRITY_MISMATCH', 'UNAVAILABLE']), assessment: tenantMaterialCurrentnessSchema.nullable() }).strict(),
64
+ tenant_material_share: routeChange, tenant_material_revoke: routeChange, tenant_material_routes: z.object({ items: z.array(route).max(100), nextAfter: z.string().nullable() }).strict(),
65
+ tenant_workflow_guide: guide, tenant_workflow_plan: tenantWorkflowPlanSchema,
66
+ tenant_workflow_advance: z.object({ schemaVersion: z.literal(2), action: z.enum(['SUBMIT_REVIEW', 'FINALIZE_REVIEW']), previousRef: tenantResourceRefSchema, inserted: z.boolean(), production, plan: tenantWorkflowPlanSchema }).strict(),
67
+ tenant_knowledge_read: governedRead,
68
+ tenant_source_define: z.object({ changed: z.boolean(), reused: z.boolean(), phase: z.literal('SOURCE_REGISTERED'), head: sourceHead }).strict(),
69
+ tenant_source_configure: z.object({ changed: z.boolean(), head: sourceHead }).strict(), tenant_source_get: sourceHead.nullable(), tenant_source_list: z.object({ items: z.array(sourceHead).max(100), nextAfter: tenantSourceIdSchema.nullable() }).strict(),
70
+ tenant_collection_request: z.object({ inserted: z.boolean(), request: tenantCollectionRequestSchema, batch: tenantCollectionBatchSchema, phase: z.literal('BATCH_PERSISTED') }).strict(),
71
+ tenant_collection_status: z.object({ request: tenantCollectionRequestSchema, completion: tenantCollectionCompletionSchema.nullable(), failure: tenantCollectionFailureSchema.nullable().optional() }).strict().nullable(),
72
+ };
73
+ export const tenantManagementErrorCodeSchema = z.enum(['TENANT_MANAGEMENT_INVALID_INPUT', 'TENANT_MANAGEMENT_FORBIDDEN', 'TENANT_MANAGEMENT_AUTHORITY_CHANGED', 'TENANT_MANAGEMENT_RUNTIME_OWNER_REQUIRED', 'TENANT_MANAGEMENT_IDEMPOTENCY_CONFLICT', 'TENANT_MANAGEMENT_VERSION_CONFLICT', 'TENANT_MANAGEMENT_SOURCE_FORBIDDEN', 'TENANT_MANAGEMENT_REVIEW_REQUIRED', 'TENANT_MANAGEMENT_POLICY_BLOCKED', 'TENANT_MANAGEMENT_UNAVAILABLE', 'TENANT_MANAGEMENT_INCOMPLETE', 'TENANT_MANAGEMENT_INPUT_BUDGET', 'TENANT_MANAGEMENT_NOT_FOUND']);
74
+ export const tenantManagementErrorSchema = z.object({ errorCode: tenantManagementErrorCodeSchema, completedPhase: z.enum(['VALIDATED', 'PERSISTED', 'CATALOG_PROJECTED', 'REGISTERED', 'ROUTE_COMMITTED', 'DECLARATION_PERSISTED', 'CURRENTNESS_RECORDED', 'CURRENTNESS_NOTIFIED', 'SOURCE_PERSISTED', 'SOURCE_REGISTERED', 'REQUEST_PERSISTED', 'BATCH_PERSISTED']).optional(), ref: stableUriSchema.optional() }).strict();
75
+ export function tenantManagementEnvelopeSchema(tool) { return z.object({ schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, tool: z.literal(tool), data: tenantManagementDataSchemas[tool] }).strict(); }
76
+ export const tenantManagementInputJsonSchemas = Object.fromEntries(Object.entries(tenantManagementToolSchemas).map(([name, schema]) => [name, z.toJSONSchema(schema, { target: 'draft-07' })]));
77
+ export const tenantManagementOutputJsonSchemas = Object.fromEntries(Object.keys(tenantManagementToolSchemas).map(name => [name, { type: 'object', oneOf: [z.toJSONSchema(tenantManagementEnvelopeSchema(name), { target: 'draft-07' }), z.toJSONSchema(tenantManagementErrorSchema, { target: 'draft-07' })] }]));
78
+ export const tenantManagementProviderBaseSchema = z.object({ schemaVersion: z.literal(17), provider: z.literal('knowledge-v2'), codeRevision: z.string().min(1).max(128), authorityVersion: z.literal(2), context: z.literal('TENANT_EXPLICIT_MANAGEMENT_V1'), managementConfigured: z.boolean(), resource: stableUriSchema, issuer: stableUriSchema, authorizationEndpoint: stableUriSchema, tokenEndpoint: stableUriSchema, revocationEndpoint: stableUriSchema, mcpEndpoint: stableUriSchema, callEndpoint: stableUriSchema, contentEndpoint: stableUriSchema, contentContextHeader: z.literal('x-knowledge-tenant-id'), legacyProviderEndpoint: stableUriSchema, protocols: z.array(z.enum(['2026-07-28', '2025-06-18'])).min(1).max(2), tools: z.array(z.string()).length(Object.keys(tenantManagementToolSchemas).length), requestMaxBytes: z.literal(131072), resultMaxBytes: z.literal(524288), submissionMaxBytes: z.literal(65536), inlineContentMaxBytes: z.literal(32768), contentReadMaxBytes: z.literal(16777216), collectionMode: z.literal('MANUAL_ONLY_OAUTH'), capabilities: z.tuple([z.literal('TENANT_MANAGEMENT_V1'), z.literal('TENANT_WORKFLOW_V1'), z.literal('TENANT_CURRENTNESS_V2'), z.literal('TENANT_SOURCE_V1')]) }).strict();
79
+ export const tenantManagementProviderSchema = tenantManagementProviderBaseSchema.superRefine((v, ctx) => { if (new Set(v.tools).size !== Object.keys(tenantManagementToolSchemas).length || v.tools.some(name => !Object.hasOwn(tenantManagementToolSchemas, name)))
80
+ ctx.addIssue({ code: 'custom', message: 'Provider tools must match the exact native tool contract' }); });
81
+ /** 诊断 ref 只允许当前访问 Tenant 的 canonical 原生身份;不接受 URL/本机路径。 */
82
+ export function tenantManagementSafeErrorRef(ref, tenantId) {
83
+ if (typeof ref !== 'string' || ref.length > 2048)
84
+ return undefined;
85
+ const key = tenantStorageKey(tenantId), resource = parseTenantResourceRef(ref);
86
+ if (resource?.storageKey === key)
87
+ return ref;
88
+ return new RegExp(`^(?:tenant-operation://${key}/[a-f0-9]{64}|tenant-collection-request://${key}/[a-f0-9]{64}|tenant-currentness://${key}/snapshot/[a-f0-9]{64}|tenant-source://${key}/[A-Za-z0-9][A-Za-z0-9._-]{0,127}(?:/v/[a-f0-9]{64})?)$`).test(ref) ? ref : undefined;
89
+ }
@@ -0,0 +1,39 @@
1
+ /** Provider19 extends Project context without changing the exact v17/v18 registries. */
2
+ import { z } from 'zod';
3
+ import { projectKeySchema, sha256Schema, stableUriSchema, isoDateTimeSchema, materialTenantIdSchema, resourceDirectoryItemSchema, tenantProjectScopeChangeSchema, tenantProjectLifecycleChangeSchema, tenantProjectControlResultSchema, tenantManagementRequestIdSchema } from '../contracts/index.js';
4
+ import { tenantWorkspaceToolSchemas, tenantWorkspaceDataSchemas, tenantWorkspaceScopesForInput, tenantWorkspaceAuthorization } from './tenant-workspace.js';
5
+ import { tenantManagementErrorSchema, tenantManagementProviderBaseSchema } from './tenant-management.js';
6
+ const cursor = z.string().min(1).max(4096), page = { after: cursor.optional(), limit: z.number().int().min(1).max(100).optional() };
7
+ export const tenantProjectToolSchemas = {
8
+ tenant_project_list: z.object(page).strict(),
9
+ tenant_project_get: z.object({ projectKey: projectKeySchema, purposeAfter: cursor.optional(), selectionAfter: cursor.optional(), requestId: tenantManagementRequestIdSchema.optional() }).strict(),
10
+ tenant_project_materials: z.object({ projectKey: projectKeySchema, ...page }).strict(),
11
+ tenant_project_scope_set: tenantProjectScopeChangeSchema,
12
+ tenant_project_lifecycle_set: tenantProjectLifecycleChangeSchema,
13
+ };
14
+ const result = tenantProjectControlResultSchema, receipt = z.object({ operationRef: stableUriSchema, action: z.enum(['SET_SCOPE', 'SET_LIFECYCLE']), result, committedAt: isoDateTimeSchema }).strict();
15
+ const purpose = z.object({ state: z.enum(['READY', 'NOT_REGISTERED', 'UNAVAILABLE', 'INTEGRITY_MISMATCH']), revisionRef: stableUriSchema.nullable(), identity: z.object({ name: z.string().max(256), summary: z.string().max(4000), domains: z.array(z.string().max(256)).max(32), domainTotal: z.number().int().min(0).max(256), notes: z.string().max(1000).nullable(), notesTruncated: z.boolean() }).strict().nullable(), scopes: z.array(z.object({ scopeId: z.string().max(128), title: z.string().max(256), description: z.string().max(512), descriptionTruncated: z.boolean(), sourceRequirementCount: z.number().int().min(0).max(256), sourceFamilyCount: z.number().int().min(0).max(256) }).strict()).max(20), scopeTotal: z.number().int().min(0).max(1000).nullable(), nextAfter: cursor.nullable() }).strict();
16
+ const selection = z.object({ state: z.enum(['READY', 'NOT_AUTHORIZED', 'UNAVAILABLE', 'BUDGET_EXCEEDED']), mode: z.enum(['TENANT', 'EXPLICIT']).nullable(), revision: sha256Schema.nullable(), selectors: z.array(z.object({ type: z.enum(['REF', 'SOURCE_PROJECT']), value: z.string().min(1).max(4096) }).strict()).max(20), nextAfter: cursor.nullable() }).strict();
17
+ export const tenantProjectDataSchemas = {
18
+ tenant_project_list: z.object({ items: z.array(z.object({ projectKey: projectKeySchema, state: z.enum(['ACTIVE', 'ARCHIVED']) }).strict()).max(100), nextAfter: cursor.nullable(), coverage: z.literal('OWN_TENANT_PROJECTS') }).strict(),
19
+ tenant_project_get: z.object({ projectKey: projectKeySchema, state: z.enum(['ACTIVE', 'ARCHIVED']), lifecycleRevision: sha256Schema, controlReady: z.boolean(), purpose, selection, receipt: receipt.nullable() }).strict(),
20
+ tenant_project_materials: z.object({ projectKey: projectKeySchema, policy: z.literal('TENANT_PROJECT_SCOPE'), items: z.array(resourceDirectoryItemSchema).max(100), nextAfter: cursor.nullable() }).strict(),
21
+ tenant_project_scope_set: z.object({ projectKey: projectKeySchema, replayed: z.boolean(), receipt, current: result, completedPhase: z.literal('PROJECT_CONTROL_COMMITTED'), operationRef: stableUriSchema }).strict(),
22
+ tenant_project_lifecycle_set: z.object({ projectKey: projectKeySchema, replayed: z.boolean(), receipt, current: result, completedPhase: z.literal('PROJECT_CONTROL_COMMITTED'), operationRef: stableUriSchema }).strict(),
23
+ };
24
+ export const tenantProjectErrorSchema = tenantManagementErrorSchema.extend({ completedPhase: z.enum([...tenantManagementErrorSchema.shape.completedPhase.unwrap().options, 'PROJECT_CONTROL_COMMITTED']).optional() }).strict();
25
+ export const tenantProjectWorkspaceToolSchemas = { ...tenantWorkspaceToolSchemas, ...tenantProjectToolSchemas };
26
+ export const tenantProjectWorkspaceDataSchemas = { ...tenantWorkspaceDataSchemas, ...tenantProjectDataSchemas };
27
+ export function tenantProjectScopesForInput(name, raw) { if (Object.hasOwn(tenantProjectToolSchemas, name)) {
28
+ tenantProjectToolSchemas[name].parse(raw);
29
+ return name === 'tenant_project_scope_set' ? ['knowledge.workflow.read', 'knowledge.material.scope'] : name === 'tenant_project_lifecycle_set' ? ['knowledge.workflow.read', 'knowledge.project.manage'] : name === 'tenant_project_materials' ? ['knowledge.material.read'] : ['knowledge.workflow.read'];
30
+ } return tenantWorkspaceScopesForInput(name, raw); }
31
+ export function tenantProjectAuthorization(name) { if (Object.hasOwn(tenantProjectToolSchemas, name)) {
32
+ const scopes = name === 'tenant_project_scope_set' ? ['knowledge.workflow.read', 'knowledge.material.scope'] : name === 'tenant_project_lifecycle_set' ? ['knowledge.workflow.read', 'knowledge.project.manage'] : name === 'tenant_project_materials' ? ['knowledge.material.read'] : ['knowledge.workflow.read'];
33
+ return { selection: 'FIXED', scopeAlternatives: [scopes] };
34
+ } return tenantWorkspaceAuthorization(name); }
35
+ export function tenantProjectEnvelopeSchema(tool) { return z.object({ schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, tool: z.literal(tool), data: tenantProjectWorkspaceDataSchemas[tool] }).strict(); }
36
+ export const tenantProjectInputJsonSchemas = Object.fromEntries(Object.entries(tenantProjectWorkspaceToolSchemas).map(([name, schema]) => [name, z.toJSONSchema(schema, { target: 'draft-07' })]));
37
+ export const tenantProjectOutputJsonSchemas = Object.fromEntries(Object.keys(tenantProjectWorkspaceToolSchemas).map(name => [name, { type: 'object', oneOf: [z.toJSONSchema(tenantProjectEnvelopeSchema(name), { target: 'draft-07' }), z.toJSONSchema(tenantProjectErrorSchema, { target: 'draft-07' })] }]));
38
+ export const tenantProjectProviderSchema = tenantManagementProviderBaseSchema.extend({ schemaVersion: z.literal(19), projectContentEndpoint: stableUriSchema, projectContentPolicyHeader: z.literal('x-knowledge-authority-policy'), projectContentProjectHeader: z.literal('x-knowledge-project-key'), projectControlIdentitySchemaVersion: z.literal(19), tools: z.array(z.string()).length(Object.keys(tenantProjectWorkspaceToolSchemas).length), capabilities: z.tuple([z.literal('TENANT_MANAGEMENT_V1'), z.literal('TENANT_WORKFLOW_V1'), z.literal('TENANT_CURRENTNESS_V2'), z.literal('TENANT_SOURCE_V1'), z.literal('TENANT_WORKSPACE_METADATA_V1'), z.literal('TENANT_PROJECT_CONTEXT_V1')]) }).strict().superRefine((value, ctx) => { if (new Set(value.tools).size !== Object.keys(tenantProjectWorkspaceToolSchemas).length || value.tools.some(name => !Object.hasOwn(tenantProjectWorkspaceToolSchemas, name)))
39
+ ctx.addIssue({ code: 'custom', message: 'Project workspace tools must match the exact version19 contract' }); });
@@ -0,0 +1,37 @@
1
+ /** Provider20只增加明确授权的运行元数据;不扩展旧版本工具或授予正文读取。 */
2
+ import { z } from 'zod';
3
+ import { materialTenantIdSchema, isoDateTimeSchema, stableUriSchema, sha256Schema, projectKeySchema, tenantResourceRefSchema, tenantBudgetPolicySchema, tenantStorageKey, parseTenantResourceRef, parseTenantCollectionBatchRef, tenantBudgetReasonSchema } from '../contracts/index.js';
4
+ import { tenantProjectWorkspaceToolSchemas, tenantProjectWorkspaceDataSchemas, tenantProjectScopesForInput, tenantProjectAuthorization, tenantProjectErrorSchema, tenantProjectProviderSchema } from './tenant-project.js';
5
+ const count = z.number().int().nonnegative().safe(), cursor = z.string().min(1).max(4096), state = z.enum(['MATCH', 'MISSING', 'UNAVAILABLE', 'INTEGRITY_MISMATCH', 'NOT_REGISTERED']);
6
+ export const tenantRuntimeKindSchema = z.enum(['REQUESTS', 'RESOURCES', 'PROJECTIONS', 'PROJECTS']);
7
+ export const tenantRuntimeInputSchema = z.object({ kind: tenantRuntimeKindSchema.default('REQUESTS'), after: cursor.optional(), limit: z.number().int().min(1).max(20).default(20), requestRef: z.string().regex(/^tenant-collection-request:\/\/[a-f0-9]{64}\/[a-f0-9]{64}$/).optional() }).strict().superRefine((v, ctx) => { if (v.requestRef && (v.kind !== 'REQUESTS' || v.after))
8
+ ctx.addIssue({ code: 'custom', message: 'Exact request lookup requires REQUESTS without a page cursor' }); });
9
+ export const tenantRuntimeProcessSchema = z.object({ runtimeNodeId: projectKeySchema, workloadId: z.string().min(1).max(256), runId: z.string().min(1).max(256), attribution: z.enum(['COMPLETION_RUN', 'FAILURE_RUN', 'SOURCE_WORKLOAD_LATEST', 'PROJECT_WORKLOAD_LATEST']), batchMatches: z.boolean().nullable(), outcome: z.enum(['SUCCEEDED', 'FAILED', 'TIMED_OUT', 'OUTPUT_LIMIT', 'SPAWN_FAILED', 'RECEIPT_MISSING']).nullable(), receiptStatus: z.enum(['SUCCEEDED', 'PARTIAL', 'FAILED', 'BLOCKED', 'SKIPPED']).nullable(), durationMs: count.nullable(), finishedAt: isoDateTimeSchema, category: z.enum(['NONE', 'TIMEOUT', 'OUTPUT_LIMIT', 'SPAWN_FAILURE', 'V8_HEAP_EXHAUSTED', 'NATIVE_ASSERTION_FAILURE', 'UNCAUGHT_EXCEPTION', 'PROCESS_SIGNAL', 'UNKNOWN_FAILURE']).nullable(), peakRssBytes: count.nullable(), sampleCount: count.nullable() }).strict();
10
+ export const tenantRuntimeResourceSchema = z.object({ ref: tenantResourceRefSchema, contentHash: sha256Schema.nullable(), recordedBytes: count.nullable(), manifest: z.enum(['PRESENT', 'MISSING', 'UNAVAILABLE', 'INTEGRITY_MISMATCH']), blob: z.enum(['PRESENT_UNVERIFIED', 'MISSING', 'UNAVAILABLE', 'INTEGRITY_MISMATCH']), contentHashReverified: z.literal(false), catalog: state, directory: state, search: state }).strict();
11
+ const request = z.object({ kind: z.literal('REQUESTS'), requestRef: stableUriSchema, batchRef: stableUriSchema, admission: z.enum(['PENDING', 'STOPPED', 'COMPLETED', 'FAILED']), failureCode: z.literal('TENANT_SOURCE_HTTP_TERMINAL').nullable().optional(), stopReason: z.enum(['GRANT_REVOKED', 'DELEGATION_SUPERSEDED']).nullable(), executionAuthority: z.enum(['CURRENT', 'BLOCKED', 'NOT_CONFIGURED', 'NOT_PENDING', 'UNAVAILABLE']), budgetReason: tenantBudgetReasonSchema.nullable(), captureRecord: z.enum(['PRESENT', 'MISSING', 'UNAVAILABLE']), raw: tenantRuntimeResourceSchema, derivation: z.enum(['NOT_REQUIRED', 'REGISTERED', 'PENDING', 'UNAVAILABLE']), completedPhase: z.enum(['RAW_REGISTERED', 'DERIVED_REGISTERED']).nullable(), process: tenantRuntimeProcessSchema.nullable() }).strict();
12
+ const resources = tenantRuntimeResourceSchema.extend({ kind: z.literal('RESOURCES') }).strict(), projection = tenantRuntimeResourceSchema.extend({ kind: z.literal('PROJECTIONS'), expectedManifestRevision: sha256Schema, preparedAt: isoDateTimeSchema }).strict();
13
+ const project = z.object({ kind: z.literal('PROJECTS'), projectKey: projectKeySchema, lifecycle: z.enum(['ACTIVE', 'ARCHIVED']), runtimeState: z.enum(['AVAILABLE', 'UNAVAILABLE']), projection: z.object({ requestedGeneration: count, completedGeneration: count, pendingGenerationDelta: count }).strict().nullable(), checkpointState: z.enum(['READY', 'UNAVAILABLE', 'EPOCH_MISMATCH']), directoryThroughSeq: count.nullable(), searchThroughSeq: count.nullable(), searchObservedMaxSeq: count.nullable(), searchSequenceDelta: count.nullable(), process: tenantRuntimeProcessSchema.nullable() }).strict();
14
+ const budget = z.discriminatedUnion('state', [
15
+ z.object({ state: z.literal('READY'), scope: z.literal('RUNTIME_OWNER_DATA_ROOT'), windowStart: isoDateTimeSchema, windowEnd: isoDateTimeSchema, usage: z.object({ inFlight: count, workUnits: count, runtimeMs: count }).strict(), limits: tenantBudgetPolicySchema, maxWaitRounds: z.number().int().min(1).max(2048) }).strict(),
16
+ z.object({ state: z.enum(['NOT_CONFIGURED', 'UNAVAILABLE']), reason: z.enum(['CONFIGURATION_REQUIRED', 'TENANT_NOT_CONFIGURED', 'BINDING_MISMATCH', 'STATE_UNAVAILABLE']) }).strict(),
17
+ ]);
18
+ export const tenantRuntimeDataSchema = z.object({ nodeId: projectKeySchema, kind: tenantRuntimeKindSchema, observedAt: isoDateTimeSchema, coverage: z.literal('OWN_TENANT_METADATA_SAMPLE'), metadataOnly: z.literal(true), pageState: z.enum(['READY', 'UNAVAILABLE']), items: z.array(z.discriminatedUnion('kind', [request, resources, projection, project])).max(20), nextAfter: cursor.nullable(), sampleCount: count.max(20), total: z.null(), budget, delivery: z.object({ headSeq: count, retainedThroughSeq: count, businessOutcome: z.literal('NOT_ASSERTED') }).strict() }).strict().superRefine((v, ctx) => { if (v.items.some(item => item.kind !== v.kind) || v.sampleCount !== v.items.length || v.pageState === 'UNAVAILABLE' && (v.items.length || v.nextAfter !== null))
19
+ ctx.addIssue({ code: 'custom', message: 'Metadata sample preserves kind and actual bounded row count' }); });
20
+ export const tenantRuntimeToolSchemas = { tenant_runtime_status: tenantRuntimeInputSchema };
21
+ export const tenantRuntimeWorkspaceToolSchemas = { ...tenantProjectWorkspaceToolSchemas, ...tenantRuntimeToolSchemas };
22
+ export const tenantRuntimeWorkspaceDataSchemas = { ...tenantProjectWorkspaceDataSchemas, tenant_runtime_status: tenantRuntimeDataSchema };
23
+ export function tenantRuntimeScopesForInput(name, raw) { if (name === 'tenant_runtime_status') {
24
+ tenantRuntimeInputSchema.parse(raw);
25
+ return ['knowledge.runtime.read'];
26
+ } return tenantProjectScopesForInput(name, raw); }
27
+ export function tenantRuntimeAuthorization(name) { return name === 'tenant_runtime_status' ? { selection: 'FIXED', scopeAlternatives: [['knowledge.runtime.read']] } : tenantProjectAuthorization(name); }
28
+ export const tenantRuntimeStatusEnvelopeSchema = z.object({ schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, tool: z.literal('tenant_runtime_status'), data: tenantRuntimeDataSchema }).strict().superRefine((value, ctx) => {
29
+ const { data } = value, key = tenantStorageKey(value.tenantId), mine = (ref) => parseTenantResourceRef(ref)?.storageKey === key;
30
+ if (data.budget.state === 'READY' && data.budget.limits.tenantId !== value.tenantId || data.items.some(item => item.kind === 'REQUESTS' ? !(new RegExp('^tenant-collection-request://' + key + '/[a-f0-9]{64}$').test(item.requestRef)) || parseTenantCollectionBatchRef(item.batchRef)?.storageKey !== key || !mine(item.raw.ref) || parseTenantResourceRef(item.raw.ref)?.resourceType !== 'evidence' : item.kind === 'PROJECTS' ? false : !mine(item.ref)))
31
+ ctx.addIssue({ code: 'custom', message: 'Runtime metadata retains exact Tenant scope' });
32
+ });
33
+ export function tenantRuntimeEnvelopeSchema(tool) { return tool === 'tenant_runtime_status' ? tenantRuntimeStatusEnvelopeSchema : z.object({ schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, tool: z.literal(tool), data: tenantRuntimeWorkspaceDataSchemas[tool] }).strict(); }
34
+ export const tenantRuntimeInputJsonSchemas = Object.fromEntries(Object.entries(tenantRuntimeWorkspaceToolSchemas).map(([name, schema]) => [name, z.toJSONSchema(schema, { target: 'draft-07' })]));
35
+ export const tenantRuntimeOutputJsonSchemas = Object.fromEntries(Object.keys(tenantRuntimeWorkspaceToolSchemas).map(name => [name, { type: 'object', oneOf: [z.toJSONSchema(tenantRuntimeEnvelopeSchema(name), { target: 'draft-07' }), z.toJSONSchema(tenantProjectErrorSchema, { target: 'draft-07' })] }]));
36
+ export const tenantRuntimeProviderSchema = z.object({ ...tenantProjectProviderSchema.shape, schemaVersion: z.literal(20), tools: z.array(z.string()).length(Object.keys(tenantRuntimeWorkspaceToolSchemas).length), capabilities: z.tuple([z.literal('TENANT_MANAGEMENT_V1'), z.literal('TENANT_WORKFLOW_V1'), z.literal('TENANT_CURRENTNESS_V2'), z.literal('TENANT_SOURCE_V1'), z.literal('TENANT_WORKSPACE_METADATA_V1'), z.literal('TENANT_PROJECT_CONTEXT_V1'), z.literal('TENANT_RUNTIME_STATUS_V1')]) }).strict().superRefine((value, ctx) => { if (new Set(value.tools).size !== Object.keys(tenantRuntimeWorkspaceToolSchemas).length || value.tools.some(name => !Object.hasOwn(tenantRuntimeWorkspaceToolSchemas, name)))
37
+ ctx.addIssue({ code: 'custom', message: 'Runtime tools must match exact version20 contract' }); });
@@ -0,0 +1,87 @@
1
+ import { z } from 'zod';
2
+ export declare const tenantSessionSchema: z.ZodObject<{
3
+ schemaVersion: z.ZodLiteral<1>;
4
+ issuer: z.ZodString;
5
+ resource: z.ZodString;
6
+ clientId: z.ZodString;
7
+ userId: z.ZodString;
8
+ tenantId: z.ZodString;
9
+ tenantRef: z.ZodString;
10
+ contextType: z.ZodLiteral<"TENANT">;
11
+ authorityVersion: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>]>;
12
+ tokenScopes: z.ZodArray<z.ZodString>;
13
+ effectiveScopes: z.ZodArray<z.ZodString>;
14
+ expiresAt: z.ZodString;
15
+ managementConfigured: z.ZodBoolean;
16
+ blockers: z.ZodArray<z.ZodString>;
17
+ }, z.core.$strict>;
18
+ export type TenantSession = z.infer<typeof tenantSessionSchema>;
19
+ export declare const tenantOperationStatusInputSchema: z.ZodObject<{
20
+ requestId: z.ZodString;
21
+ }, z.core.$strict>;
22
+ export declare const tenantOperationStatusSchema: z.ZodObject<{
23
+ schemaVersion: z.ZodLiteral<1>;
24
+ tenantId: z.ZodString;
25
+ requestId: z.ZodString;
26
+ state: z.ZodEnum<{
27
+ NOT_FOUND: "NOT_FOUND";
28
+ INTENT_PERSISTED: "INTENT_PERSISTED";
29
+ }>;
30
+ operationRef: z.ZodNullable<z.ZodString>;
31
+ action: z.ZodNullable<z.ZodString>;
32
+ receivedAt: z.ZodNullable<z.ZodString>;
33
+ completion: z.ZodLiteral<"NOT_PROVEN">;
34
+ }, z.core.$strict>;
35
+ export declare const tenantClientProviderSchema: z.ZodObject<{
36
+ schemaVersion: z.ZodLiteral<26>;
37
+ provider: z.ZodLiteral<"knowledge-v2">;
38
+ revision: z.ZodString;
39
+ issuer: z.ZodString;
40
+ resource: z.ZodString;
41
+ authorizationServerMetadataUrl: z.ZodString;
42
+ tenantSessionEndpoint: z.ZodString;
43
+ tenantOperationStatusEndpoint: z.ZodString;
44
+ resourceCallEndpoint: z.ZodString;
45
+ resourceFileEndpoint: z.ZodString;
46
+ registrationModes: z.ZodArray<z.ZodEnum<{
47
+ PRE_REGISTERED_NATIVE: "PRE_REGISTERED_NATIVE";
48
+ CIMD_READ_ONLY: "CIMD_READ_ONLY";
49
+ }>>;
50
+ callbackModes: z.ZodArray<z.ZodLiteral<"NATIVE_LOOPBACK_PORT_V1">>;
51
+ providers: z.ZodArray<z.ZodObject<{
52
+ version: z.ZodNumber;
53
+ endpoint: z.ZodString;
54
+ }, z.core.$strict>>;
55
+ tools: z.ZodArray<z.ZodObject<{
56
+ name: z.ZodString;
57
+ endpoint: z.ZodString;
58
+ method: z.ZodDefault<z.ZodEnum<{
59
+ GET: "GET";
60
+ POST: "POST";
61
+ }>>;
62
+ inputSchema: z.ZodJSONSchema;
63
+ outputSchema: z.ZodJSONSchema;
64
+ scopeAlternatives: z.ZodArray<z.ZodArray<z.ZodString>>;
65
+ }, z.core.$strict>>;
66
+ limits: z.ZodObject<{
67
+ requestMaxBytes: z.ZodLiteral<131072>;
68
+ resultMaxBytes: z.ZodLiteral<524288>;
69
+ }, z.core.$strict>;
70
+ }, z.core.$strict>;
71
+ export type TenantClientProvider = z.infer<typeof tenantClientProviderSchema>;
72
+ export declare const tenantOperationStatusInputJsonSchema: z.core.ZodStandardJSONSchemaPayload<z.ZodObject<{
73
+ requestId: z.ZodString;
74
+ }, z.core.$strict>>;
75
+ export declare const tenantOperationStatusOutputJsonSchema: z.core.ZodStandardJSONSchemaPayload<z.ZodObject<{
76
+ schemaVersion: z.ZodLiteral<1>;
77
+ tenantId: z.ZodString;
78
+ requestId: z.ZodString;
79
+ state: z.ZodEnum<{
80
+ NOT_FOUND: "NOT_FOUND";
81
+ INTENT_PERSISTED: "INTENT_PERSISTED";
82
+ }>;
83
+ operationRef: z.ZodNullable<z.ZodString>;
84
+ action: z.ZodNullable<z.ZodString>;
85
+ receivedAt: z.ZodNullable<z.ZodString>;
86
+ completion: z.ZodLiteral<"NOT_PROVEN">;
87
+ }, z.core.$strict>>;
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+ const endpoint = z.string().url(), id = z.string().min(1).max(512), scopes = z.array(z.string().min(1).max(100)).max(32);
3
+ export const tenantSessionSchema = z.object({ schemaVersion: z.literal(1), issuer: endpoint, resource: endpoint, clientId: id, userId: id, tenantId: id, tenantRef: z.string().startsWith('knowledge-tenant://'), contextType: z.literal('TENANT'), authorityVersion: z.union([z.literal(1), z.literal(2)]), tokenScopes: scopes, effectiveScopes: scopes, expiresAt: z.string().datetime(), managementConfigured: z.boolean(), blockers: z.array(z.string()).max(16) }).strict();
4
+ export const tenantOperationStatusInputSchema = z.object({ requestId: z.string().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9._:-]*$/) }).strict();
5
+ export const tenantOperationStatusSchema = z.object({ schemaVersion: z.literal(1), tenantId: id, requestId: z.string(), state: z.enum(['NOT_FOUND', 'INTENT_PERSISTED']), operationRef: z.string().nullable(), action: z.string().nullable(), receivedAt: z.string().datetime().nullable(), completion: z.literal('NOT_PROVEN') }).strict();
6
+ export const tenantClientProviderSchema = z.object({ schemaVersion: z.literal(26), provider: z.literal('knowledge-v2'), revision: z.string(), issuer: endpoint, resource: endpoint, authorizationServerMetadataUrl: endpoint, tenantSessionEndpoint: endpoint, tenantOperationStatusEndpoint: endpoint, resourceCallEndpoint: endpoint, resourceFileEndpoint: endpoint, registrationModes: z.array(z.enum(['PRE_REGISTERED_NATIVE', 'CIMD_READ_ONLY'])).max(2), callbackModes: z.array(z.literal('NATIVE_LOOPBACK_PORT_V1')).max(1), providers: z.array(z.object({ version: z.number().int().min(16).max(26), endpoint }).strict()).max(11), tools: z.array(z.object({ name: z.string(), endpoint, method: z.enum(['GET', 'POST']).default('POST'), inputSchema: z.json(), outputSchema: z.json(), scopeAlternatives: z.array(scopes).max(8) }).strict()).max(100), limits: z.object({ requestMaxBytes: z.literal(131072), resultMaxBytes: z.literal(524288) }).strict() }).strict();
7
+ export const tenantOperationStatusInputJsonSchema = z.toJSONSchema(tenantOperationStatusInputSchema, { target: 'draft-07' });
8
+ export const tenantOperationStatusOutputJsonSchema = z.toJSONSchema(tenantOperationStatusSchema, { target: 'draft-07' });
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ import { tenantWebContentDocumentSchema, tenantWebContentInputSchema, tenantWebContentPlanSchema, tenantWebContentStatusSchema, tenantWebContentOutcomeSchema, tenantWebJobRefSchema, materialTenantIdSchema, tenantStorageKey, tenantWebContentRevision, tenantWebDynamicSpecRevision } from '../contracts/index.js';
3
+ import { tenantWebDynamicToolSchemas, tenantWebDynamicWorkspaceToolSchemas, tenantWebDynamicDataSchemas, tenantWebDynamicProviderSchema } from './tenant-web-dynamic.js';
4
+ import { tenantWebErrorSchema, tenantWebScopesForInput } from './tenant-web.js';
5
+ import { tenantRuntimeEnvelopeSchema } from './tenant-runtime.js';
6
+ const extraction = tenantWebContentInputSchema.default({ mode: 'NATURAL_LANGUAGE' });
7
+ export const tenantWebContentToolSchemas = { tenant_web_collect_preview: z.object({ ...tenantWebDynamicToolSchemas.tenant_web_collect_preview.shape, extraction }).strict(), tenant_web_collect_submit: z.object({ ...tenantWebDynamicToolSchemas.tenant_web_collect_submit.shape, extraction, retainedFrom: tenantWebJobRefSchema.nullable().default(null) }).strict(), tenant_web_collect_status: z.object({ ...tenantWebDynamicToolSchemas.tenant_web_collect_status.shape, resultIndex: z.number().int().min(0).max(21999).optional(), includeContent: z.boolean().default(false) }).strict().refine(v => !v.includeContent || v.resultIndex !== undefined) };
8
+ export const tenantWebContentWorkspaceToolSchemas = { ...tenantWebDynamicWorkspaceToolSchemas, ...tenantWebContentToolSchemas };
9
+ export const tenantWebContentErrorSchema = z.object({ ...tenantWebErrorSchema.shape, errorCode: z.enum([...tenantWebErrorSchema.shape.errorCode.options, 'TENANT_WEB_SEMANTIC_COMPILER_UNAVAILABLE', 'TENANT_WEB_CONTENT_FIELD_PLAN_REQUIRED', 'TENANT_WEB_RETAINED_SCOPE_FORBIDDEN', 'TENANT_WEB_RESULT_NOT_FOUND']) }).strict();
10
+ export const tenantWebContentDataSchemas = { tenant_web_collect_preview: z.object({ spec: tenantWebDynamicDataSchemas.tenant_web_collect_preview.shape.spec, specRevision: tenantWebDynamicDataSchemas.tenant_web_collect_preview.shape.specRevision, contentPlan: tenantWebContentPlanSchema, contentRevision: tenantWebContentStatusSchema.shape.contentRevision, networkValidated: z.literal(false), budgetReserved: z.literal(false), execution: z.literal('EXPLICIT_HOST_DISPATCH'), requirementsState: z.literal('PENDING') }).strict().refine(v => v.contentRevision === tenantWebContentRevision(v.contentPlan) && v.specRevision === tenantWebDynamicSpecRevision(v.spec)), tenant_web_collect_submit: z.object({ inserted: z.boolean(), job: tenantWebContentStatusSchema }).strict(), tenant_web_collect_status: z.object({ ...tenantWebContentStatusSchema.shape, result: tenantWebContentOutcomeSchema.nullable(), resultDocument: tenantWebContentDocumentSchema.nullable(), resultDelivery: z.enum(['NONE', 'INLINE', 'DOWNLOAD']) }).strict() };
11
+ export function tenantWebContentEnvelopeSchema(tool) { return z.object({ schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, tool: z.literal(tool), data: tenantWebContentDataSchemas[tool] }).strict().superRefine((v, c) => { const data = v.data, key = tenantStorageKey(v.tenantId), ref = data.jobRef ?? data.job?.jobRef; if (data.resultDocument && (data.resultDocument.jobRef !== ref || !data.resultDocument.parentEvidenceRef.startsWith('tenant-resource://' + key + '/evidence/')))
12
+ c.addIssue({ code: 'custom', message: 'Exact result document required' }); if (ref && !ref.startsWith('tenant-web-collection://' + key + '/') || data.result?.documentRef && !data.result.documentRef.startsWith('tenant-resource://' + key + '/source_document/'))
13
+ c.addIssue({ code: 'custom', message: 'Exact Tenant content identity required' }); }); }
14
+ export function tenantWebContentScopesForInput(name, raw) { if (Object.hasOwn(tenantWebContentToolSchemas, name)) {
15
+ const input = tenantWebContentToolSchemas[name].parse(raw);
16
+ return name === 'tenant_web_collect_status' && 'includeContent' in input && input.includeContent ? ['knowledge.collect', 'knowledge.material.read'] : name === 'tenant_web_collect_status' ? ['knowledge.collect'] : ['knowledge.source.manage', 'knowledge.collect'];
17
+ } return tenantWebScopesForInput(name, raw); }
18
+ export const tenantWebContentInputJsonSchemas = Object.fromEntries(Object.entries(tenantWebContentWorkspaceToolSchemas).map(([name, schema]) => [name, z.toJSONSchema(schema, { target: 'draft-07' })]));
19
+ export const tenantWebContentOutputJsonSchemas = Object.fromEntries(Object.keys(tenantWebContentWorkspaceToolSchemas).map(name => [name, { type: 'object', oneOf: [z.toJSONSchema(Object.hasOwn(tenantWebContentToolSchemas, name) ? tenantWebContentEnvelopeSchema(name) : tenantRuntimeEnvelopeSchema(name), { target: 'draft-07' }), z.toJSONSchema(tenantWebContentErrorSchema, { target: 'draft-07' })] }]));
20
+ export const tenantWebContentProviderSchema = z.object({ ...tenantWebDynamicProviderSchema.shape, schemaVersion: z.literal(24), capabilities: z.tuple([z.literal('TENANT_MANAGEMENT_V1'), z.literal('TENANT_WORKFLOW_V1'), z.literal('TENANT_CURRENTNESS_V2'), z.literal('TENANT_SOURCE_V1'), z.literal('TENANT_WORKSPACE_METADATA_V1'), z.literal('TENANT_PROJECT_CONTEXT_V1'), z.literal('TENANT_RUNTIME_STATUS_V1'), z.literal('TENANT_WEB_COLLECTION_SPEC_V1'), z.literal('TENANT_WEB_CRAWL_V1'), z.literal('TENANT_WEB_DYNAMIC_V1'), z.literal('TENANT_WEB_CONTENT_V1')]) }).strict().refine(v => new Set(v.tools).size === Object.keys(tenantWebContentWorkspaceToolSchemas).length && v.tools.every(t => Object.hasOwn(tenantWebContentWorkspaceToolSchemas, t)));
@@ -0,0 +1,13 @@
1
+ /** Provider22 与 Provider21 共享输入名字,执行合同通过新版本显式选择。 */
2
+ import { z } from 'zod';
3
+ import { tenantWebCrawlStatusSchema, materialTenantIdSchema, tenantStorageKey, tenantWebSpecRevision, TENANT_WEB_CRAWL_CAPABILITY } from '../contracts/index.js';
4
+ import { tenantWebToolSchemas, tenantWebWorkspaceToolSchemas, tenantWebProviderSchema, tenantWebDataSchemas, tenantWebErrorSchema, tenantWebInputJsonSchemas } from './tenant-web.js';
5
+ import { tenantRuntimeEnvelopeSchema } from './tenant-runtime.js';
6
+ export const tenantWebCrawlDataSchemas = { tenant_web_collect_preview: z.object({ spec: tenantWebDataSchemas.tenant_web_collect_preview.shape.spec, specRevision: tenantWebDataSchemas.tenant_web_collect_preview.shape.specRevision, networkValidated: z.literal(false), budgetReserved: z.literal(false), execution: z.literal('EXPLICIT_HOST_DISPATCH'), requirementsState: z.literal('DECLARED_NOT_EVALUATED') }).strict().superRefine((v, ctx) => { if (v.specRevision !== tenantWebSpecRevision(v.spec))
7
+ ctx.addIssue({ code: 'custom', message: 'Preview specification mismatch' }); }), tenant_web_collect_submit: z.object({ inserted: z.boolean(), job: tenantWebCrawlStatusSchema }).strict(), tenant_web_collect_status: tenantWebCrawlStatusSchema };
8
+ export function tenantWebCrawlEnvelopeSchema(tool) { return z.object({ schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, tool: z.literal(tool), data: tenantWebCrawlDataSchemas[tool] }).strict().superRefine((v, ctx) => { const row = v, ref = row.data.jobRef ?? row.data.job?.jobRef; if (ref && !ref.startsWith('tenant-web-collection://' + tenantStorageKey(row.tenantId) + '/'))
9
+ ctx.addIssue({ code: 'custom', message: 'Exact Tenant website job required' }); }); }
10
+ export const tenantWebCrawlInputJsonSchemas = tenantWebInputJsonSchemas;
11
+ export const tenantWebCrawlOutputJsonSchemas = Object.fromEntries(Object.keys(tenantWebWorkspaceToolSchemas).map(name => [name, { type: 'object', oneOf: [z.toJSONSchema(Object.hasOwn(tenantWebToolSchemas, name) ? tenantWebCrawlEnvelopeSchema(name) : tenantRuntimeEnvelopeSchema(name), { target: 'draft-07' }), z.toJSONSchema(tenantWebErrorSchema, { target: 'draft-07' })] }]));
12
+ export const tenantWebCrawlProviderSchema = z.object({ ...tenantWebProviderSchema.shape, schemaVersion: z.literal(22), capabilities: z.tuple([z.literal('TENANT_MANAGEMENT_V1'), z.literal('TENANT_WORKFLOW_V1'), z.literal('TENANT_CURRENTNESS_V2'), z.literal('TENANT_SOURCE_V1'), z.literal('TENANT_WORKSPACE_METADATA_V1'), z.literal('TENANT_PROJECT_CONTEXT_V1'), z.literal('TENANT_RUNTIME_STATUS_V1'), z.literal('TENANT_WEB_COLLECTION_SPEC_V1'), z.literal(TENANT_WEB_CRAWL_CAPABILITY)]) }).strict().superRefine((v, ctx) => { if (new Set(v.tools).size !== Object.keys(tenantWebWorkspaceToolSchemas).length || v.tools.some(name => !Object.hasOwn(tenantWebWorkspaceToolSchemas, name)))
13
+ ctx.addIssue({ code: 'custom', message: 'Provider22 exact registry required' }); });
@@ -0,0 +1,20 @@
1
+ /** Provider23 与 Provider21 共享输入名字,执行合同通过新版本显式选择。 */
2
+ import { z } from 'zod';
3
+ import { tenantWebDynamicSpecSchema, tenantWebDynamicStatusSchema, materialTenantIdSchema, tenantStorageKey, tenantWebDynamicSpecRevision, TENANT_WEB_DYNAMIC_CAPABILITY } from '../contracts/index.js';
4
+ import { tenantWebToolSchemas, tenantWebWorkspaceToolSchemas, tenantWebProviderSchema, tenantWebDataSchemas, tenantWebErrorSchema, tenantWebInputJsonSchemas, tenantWebScopesForInput } from './tenant-web.js';
5
+ import { tenantWebCrawlProviderSchema } from './tenant-web-crawl.js';
6
+ export const tenantWebDynamicToolSchemas = { ...tenantWebToolSchemas, tenant_web_collect_preview: z.object({ spec: tenantWebDynamicSpecSchema }).strict(), tenant_web_collect_submit: z.object({ ...tenantWebToolSchemas.tenant_web_collect_submit.shape, spec: tenantWebDynamicSpecSchema }).strict() };
7
+ export const tenantWebDynamicWorkspaceToolSchemas = { ...tenantWebWorkspaceToolSchemas, ...tenantWebDynamicToolSchemas };
8
+ export function tenantWebDynamicScopesForInput(name, raw) { if (Object.hasOwn(tenantWebDynamicToolSchemas, name)) {
9
+ tenantWebDynamicToolSchemas[name].parse(raw);
10
+ return name === 'tenant_web_collect_status' ? ['knowledge.collect'] : ['knowledge.source.manage', 'knowledge.collect'];
11
+ } return tenantWebScopesForInput(name, raw); }
12
+ import { tenantRuntimeEnvelopeSchema } from './tenant-runtime.js';
13
+ export const tenantWebDynamicDataSchemas = { tenant_web_collect_preview: z.object({ spec: tenantWebDynamicSpecSchema, specRevision: tenantWebDataSchemas.tenant_web_collect_preview.shape.specRevision, networkValidated: z.literal(false), budgetReserved: z.literal(false), execution: z.literal('EXPLICIT_HOST_DISPATCH'), requirementsState: z.literal('DECLARED_NOT_EVALUATED') }).strict().superRefine((v, ctx) => { if (v.specRevision !== tenantWebDynamicSpecRevision(v.spec))
14
+ ctx.addIssue({ code: 'custom', message: 'Preview specification mismatch' }); }), tenant_web_collect_submit: z.object({ inserted: z.boolean(), job: tenantWebDynamicStatusSchema }).strict(), tenant_web_collect_status: tenantWebDynamicStatusSchema };
15
+ export function tenantWebDynamicEnvelopeSchema(tool) { return z.object({ schemaVersion: z.literal(2), tenantId: materialTenantIdSchema, tool: z.literal(tool), data: tenantWebDynamicDataSchemas[tool] }).strict().superRefine((v, ctx) => { const row = v, ref = row.data.jobRef ?? row.data.job?.jobRef; if (ref && !ref.startsWith('tenant-web-collection://' + tenantStorageKey(row.tenantId) + '/'))
16
+ ctx.addIssue({ code: 'custom', message: 'Exact Tenant website job required' }); }); }
17
+ export const tenantWebDynamicInputJsonSchemas = Object.fromEntries(Object.entries(tenantWebDynamicWorkspaceToolSchemas).map(([name, schema]) => [name, z.toJSONSchema(schema, { target: 'draft-07' })]));
18
+ export const tenantWebDynamicOutputJsonSchemas = Object.fromEntries(Object.keys(tenantWebWorkspaceToolSchemas).map(name => [name, { type: 'object', oneOf: [z.toJSONSchema(Object.hasOwn(tenantWebToolSchemas, name) ? tenantWebDynamicEnvelopeSchema(name) : tenantRuntimeEnvelopeSchema(name), { target: 'draft-07' }), z.toJSONSchema(tenantWebErrorSchema, { target: 'draft-07' })] }]));
19
+ export const tenantWebDynamicProviderSchema = z.object({ ...tenantWebCrawlProviderSchema.shape, schemaVersion: z.literal(23), capabilities: z.tuple([z.literal('TENANT_MANAGEMENT_V1'), z.literal('TENANT_WORKFLOW_V1'), z.literal('TENANT_CURRENTNESS_V2'), z.literal('TENANT_SOURCE_V1'), z.literal('TENANT_WORKSPACE_METADATA_V1'), z.literal('TENANT_PROJECT_CONTEXT_V1'), z.literal('TENANT_RUNTIME_STATUS_V1'), z.literal('TENANT_WEB_COLLECTION_SPEC_V1'), z.literal('TENANT_WEB_CRAWL_V1'), z.literal(TENANT_WEB_DYNAMIC_CAPABILITY)]) }).strict().superRefine((v, ctx) => { if (new Set(v.tools).size !== Object.keys(tenantWebWorkspaceToolSchemas).length || v.tools.some(name => !Object.hasOwn(tenantWebWorkspaceToolSchemas, name)))
20
+ ctx.addIssue({ code: 'custom', message: 'Provider23 exact registry required' }); });