@zihanw/pi-forge 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/CHANGELOG.md +196 -0
  2. package/PUBLIC_API.md +5 -0
  3. package/README.md +93 -478
  4. package/README.zh-CN.md +88 -461
  5. package/SUBAGENT_ADAPTER_CONTRACT.md +5 -0
  6. package/dist/agent-profile.d.ts +71 -0
  7. package/dist/agent-profile.d.ts.map +1 -0
  8. package/dist/agent-profile.js +303 -0
  9. package/dist/agent-profile.js.map +1 -0
  10. package/dist/forge-config.d.ts +88 -0
  11. package/dist/forge-config.d.ts.map +1 -0
  12. package/dist/forge-config.js +290 -0
  13. package/dist/forge-config.js.map +1 -0
  14. package/dist/forge-extensions.d.ts.map +1 -1
  15. package/dist/forge-extensions.js +19 -3
  16. package/dist/forge-extensions.js.map +1 -1
  17. package/dist/index.d.ts +4 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +97 -358
  20. package/dist/index.js.map +1 -1
  21. package/dist/lifecycle.d.ts +11 -3
  22. package/dist/lifecycle.d.ts.map +1 -1
  23. package/dist/lifecycle.js +90 -4
  24. package/dist/lifecycle.js.map +1 -1
  25. package/dist/loader.d.ts.map +1 -1
  26. package/dist/loader.js +116 -5
  27. package/dist/loader.js.map +1 -1
  28. package/dist/payload-capture.d.ts.map +1 -1
  29. package/dist/payload-capture.js +27 -0
  30. package/dist/payload-capture.js.map +1 -1
  31. package/dist/payload-command.d.ts +3 -3
  32. package/dist/payload-command.d.ts.map +1 -1
  33. package/dist/payload-command.js.map +1 -1
  34. package/dist/preview.d.ts +2 -2
  35. package/dist/preview.d.ts.map +1 -1
  36. package/dist/preview.js +2 -3
  37. package/dist/preview.js.map +1 -1
  38. package/dist/profile-command.d.ts +12 -0
  39. package/dist/profile-command.d.ts.map +1 -0
  40. package/dist/profile-command.js +291 -0
  41. package/dist/profile-command.js.map +1 -0
  42. package/dist/profile-service.d.ts +103 -0
  43. package/dist/profile-service.d.ts.map +1 -0
  44. package/dist/profile-service.js +220 -0
  45. package/dist/profile-service.js.map +1 -0
  46. package/dist/runtime/profile-runtime.d.ts +13 -0
  47. package/dist/runtime/profile-runtime.d.ts.map +1 -0
  48. package/dist/runtime/profile-runtime.js +47 -0
  49. package/dist/runtime/profile-runtime.js.map +1 -0
  50. package/dist/runtime/prompt-stack-runtime.d.ts +22 -0
  51. package/dist/runtime/prompt-stack-runtime.d.ts.map +1 -0
  52. package/dist/runtime/prompt-stack-runtime.js +104 -0
  53. package/dist/runtime/prompt-stack-runtime.js.map +1 -0
  54. package/dist/runtime/subagent-runtime.d.ts +45 -0
  55. package/dist/runtime/subagent-runtime.d.ts.map +1 -0
  56. package/dist/runtime/subagent-runtime.js +335 -0
  57. package/dist/runtime/subagent-runtime.js.map +1 -0
  58. package/dist/runtime/tool-policy-runtime.d.ts +15 -0
  59. package/dist/runtime/tool-policy-runtime.d.ts.map +1 -0
  60. package/dist/runtime/tool-policy-runtime.js +170 -0
  61. package/dist/runtime/tool-policy-runtime.js.map +1 -0
  62. package/dist/runtime/web-editor-runtime.d.ts +9 -0
  63. package/dist/runtime/web-editor-runtime.d.ts.map +1 -0
  64. package/dist/runtime/web-editor-runtime.js +131 -0
  65. package/dist/runtime/web-editor-runtime.js.map +1 -0
  66. package/dist/runtime-state.d.ts +4 -0
  67. package/dist/runtime-state.d.ts.map +1 -1
  68. package/dist/runtime-state.js +2 -0
  69. package/dist/runtime-state.js.map +1 -1
  70. package/dist/storage.d.ts +4 -0
  71. package/dist/storage.d.ts.map +1 -1
  72. package/dist/storage.js +24 -1
  73. package/dist/storage.js.map +1 -1
  74. package/dist/subagent/canonical.d.ts +22 -0
  75. package/dist/subagent/canonical.d.ts.map +1 -0
  76. package/dist/subagent/canonical.js +24 -0
  77. package/dist/subagent/canonical.js.map +1 -0
  78. package/dist/subagent/context.d.ts +8 -0
  79. package/dist/subagent/context.d.ts.map +1 -0
  80. package/dist/subagent/context.js +125 -0
  81. package/dist/subagent/context.js.map +1 -0
  82. package/dist/subagent/contract.d.ts +10 -0
  83. package/dist/subagent/contract.d.ts.map +1 -0
  84. package/dist/subagent/contract.js +10 -0
  85. package/dist/subagent/contract.js.map +1 -0
  86. package/dist/subagent/index.d.ts +14 -0
  87. package/dist/subagent/index.d.ts.map +1 -0
  88. package/dist/subagent/index.js +14 -0
  89. package/dist/subagent/index.js.map +1 -0
  90. package/dist/subagent/plan.d.ts +18 -0
  91. package/dist/subagent/plan.d.ts.map +1 -0
  92. package/dist/subagent/plan.js +157 -0
  93. package/dist/subagent/plan.js.map +1 -0
  94. package/dist/subagent/preflight.d.ts +4 -0
  95. package/dist/subagent/preflight.d.ts.map +1 -0
  96. package/dist/subagent/preflight.js +108 -0
  97. package/dist/subagent/preflight.js.map +1 -0
  98. package/dist/subagent/request.d.ts +4 -0
  99. package/dist/subagent/request.d.ts.map +1 -0
  100. package/dist/subagent/request.js +122 -0
  101. package/dist/subagent/request.js.map +1 -0
  102. package/dist/subagent/response.d.ts +8 -0
  103. package/dist/subagent/response.d.ts.map +1 -0
  104. package/dist/subagent/response.js +155 -0
  105. package/dist/subagent/response.js.map +1 -0
  106. package/dist/subagent/tools.d.ts +4 -0
  107. package/dist/subagent/tools.d.ts.map +1 -0
  108. package/dist/subagent/tools.js +42 -0
  109. package/dist/subagent/tools.js.map +1 -0
  110. package/dist/subagent/types.d.ts +268 -0
  111. package/dist/subagent/types.d.ts.map +1 -0
  112. package/dist/subagent/types.js +3 -0
  113. package/dist/subagent/types.js.map +1 -0
  114. package/dist/subagent/validation.d.ts +35 -0
  115. package/dist/subagent/validation.d.ts.map +1 -0
  116. package/dist/subagent/validation.js +314 -0
  117. package/dist/subagent/validation.js.map +1 -0
  118. package/dist/subagent-command.d.ts +4 -0
  119. package/dist/subagent-command.d.ts.map +1 -0
  120. package/dist/subagent-command.js +246 -0
  121. package/dist/subagent-command.js.map +1 -0
  122. package/dist/subagent-host.d.ts +44 -0
  123. package/dist/subagent-host.d.ts.map +1 -0
  124. package/dist/subagent-host.js +292 -0
  125. package/dist/subagent-host.js.map +1 -0
  126. package/dist/subagent-profile-tool.d.ts +49 -0
  127. package/dist/subagent-profile-tool.d.ts.map +1 -0
  128. package/dist/subagent-profile-tool.js +124 -0
  129. package/dist/subagent-profile-tool.js.map +1 -0
  130. package/dist/subagent-tool.d.ts +53 -0
  131. package/dist/subagent-tool.d.ts.map +1 -0
  132. package/dist/subagent-tool.js +456 -0
  133. package/dist/subagent-tool.js.map +1 -0
  134. package/dist/web-editor/client-script.d.ts +2 -0
  135. package/dist/web-editor/client-script.d.ts.map +1 -0
  136. package/dist/web-editor/client-script.generated.d.ts +2 -0
  137. package/dist/web-editor/client-script.generated.d.ts.map +1 -0
  138. package/dist/web-editor/client-script.generated.js +3 -0
  139. package/dist/web-editor/client-script.generated.js.map +1 -0
  140. package/dist/web-editor/client-script.js +2 -0
  141. package/dist/web-editor/client-script.js.map +1 -0
  142. package/dist/web-editor/client-styles.d.ts +2 -0
  143. package/dist/web-editor/client-styles.d.ts.map +1 -0
  144. package/dist/web-editor/client-styles.generated.d.ts +2 -0
  145. package/dist/web-editor/client-styles.generated.d.ts.map +1 -0
  146. package/dist/web-editor/client-styles.generated.js +3 -0
  147. package/dist/web-editor/client-styles.generated.js.map +1 -0
  148. package/dist/web-editor/client-styles.js +2 -0
  149. package/dist/web-editor/client-styles.js.map +1 -0
  150. package/dist/web-editor/page.d.ts +2 -0
  151. package/dist/web-editor/page.d.ts.map +1 -1
  152. package/dist/web-editor/page.js +14 -3319
  153. package/dist/web-editor/page.js.map +1 -1
  154. package/dist/web-editor/server.d.ts.map +1 -1
  155. package/dist/web-editor/server.js +148 -0
  156. package/dist/web-editor/server.js.map +1 -1
  157. package/dist/web-editor/styles.d.ts +2 -0
  158. package/dist/web-editor/styles.d.ts.map +1 -0
  159. package/dist/web-editor/styles.js +1053 -0
  160. package/dist/web-editor/styles.js.map +1 -0
  161. package/dist/web-editor/types.d.ts +79 -0
  162. package/dist/web-editor/types.d.ts.map +1 -1
  163. package/dist/web-host.d.ts +16 -5
  164. package/dist/web-host.d.ts.map +1 -1
  165. package/dist/web-host.js +307 -0
  166. package/dist/web-host.js.map +1 -1
  167. package/docs/README.md +41 -0
  168. package/docs/concepts/agent-profiles.md +60 -0
  169. package/docs/concepts/prompt-stacks.md +90 -0
  170. package/docs/design/README.md +17 -0
  171. package/docs/design/roadmap-0.4-archive.md +216 -0
  172. package/docs/design/subagents/design-review.md +220 -0
  173. package/docs/design/subagents/interface-design.md +274 -0
  174. package/docs/design/subagents/sdk-spike-findings.md +117 -0
  175. package/docs/development/complexity-review.md +86 -0
  176. package/docs/development/release.md +31 -0
  177. package/docs/development/roadmap.md +42 -0
  178. package/docs/development/setup.md +75 -0
  179. package/docs/getting-started.md +93 -0
  180. package/docs/guides/custom-macros-and-slots.md +68 -0
  181. package/docs/guides/debugging.md +39 -0
  182. package/docs/guides/delegation.md +99 -0
  183. package/docs/guides/sillytavern-import.md +47 -0
  184. package/docs/guides/use-cases.md +65 -0
  185. package/docs/guides/web-editor.md +75 -0
  186. package/docs/reference/commands.md +60 -0
  187. package/docs/reference/configuration.md +64 -0
  188. package/docs/reference/features.md +279 -0
  189. package/docs/reference/macros-and-slots.md +82 -0
  190. package/docs/reference/public-api.md +28 -0
  191. package/docs/reference/stack-schema.md +167 -0
  192. package/docs/reference/subagent-adapter.md +204 -0
  193. package/docs/zh-CN/README.md +37 -0
  194. package/docs/zh-CN/concepts/agent-profiles.md +44 -0
  195. package/docs/zh-CN/concepts/prompt-stacks.md +40 -0
  196. package/docs/zh-CN/getting-started.md +79 -0
  197. package/docs/zh-CN/guides/delegation.md +66 -0
  198. package/docs/zh-CN/guides/web-editor.md +45 -0
  199. package/docs/zh-CN/reference/commands.md +58 -0
  200. package/package.json +55 -13
  201. package/src/compiler.ts +0 -578
  202. package/src/extension-registry.ts +0 -33
  203. package/src/forge-extensions.ts +0 -223
  204. package/src/index.ts +0 -445
  205. package/src/lifecycle.ts +0 -171
  206. package/src/loader.ts +0 -394
  207. package/src/macro-engine.ts +0 -358
  208. package/src/payload-capture.ts +0 -85
  209. package/src/payload-command.ts +0 -138
  210. package/src/policy.ts +0 -42
  211. package/src/preset-command.ts +0 -280
  212. package/src/preview.ts +0 -226
  213. package/src/regex.ts +0 -500
  214. package/src/render-helpers.ts +0 -169
  215. package/src/runtime-state.ts +0 -40
  216. package/src/sillytavern-importer/items.ts +0 -98
  217. package/src/sillytavern-importer/macros.ts +0 -159
  218. package/src/sillytavern-importer/prompt-order.ts +0 -54
  219. package/src/sillytavern-importer/regex.ts +0 -270
  220. package/src/sillytavern-importer/report.ts +0 -202
  221. package/src/sillytavern-importer/types.ts +0 -120
  222. package/src/sillytavern-importer.ts +0 -152
  223. package/src/slot-renderers.ts +0 -414
  224. package/src/stack-migration.ts +0 -159
  225. package/src/storage.ts +0 -45
  226. package/src/types.ts +0 -209
  227. package/src/web-editor/index.ts +0 -2
  228. package/src/web-editor/page.ts +0 -3330
  229. package/src/web-editor/server.ts +0 -294
  230. package/src/web-editor/types.ts +0 -98
  231. package/src/web-host.ts +0 -232
@@ -0,0 +1,268 @@
1
+ import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
2
+ import type { AgentProfile, AgentProfileModelReference } from "../agent-profile.ts";
3
+ import type { PromptStack } from "../types.ts";
4
+ import type { AccessCapabilities, AccessLevel, AccessReceipt, AccessRequest, BackendCapabilities, BackendDescriptor, BackendTool, Diagnostic, DiagnosticLevel, EnforcedLimit, Fingerprint, LimitEnforcement, LimitName, LimitReceipt, LimitRequest, LimitRequirement, LimitRequirementLevel, MediaReference, MountMapping, NetworkPolicy, WorkspaceMode, WorkspaceRequest, WorkingDirectoryRequest, PreparedContentPart, PreparedMessage, PreparedMessageRole, PromptRuntime, PromptRuntimeOptions, PromptRuntimeSkill, RunError, RunUsage, ToolEffect, ExecutionBoundary } from "@zihanw/pi-subagent-runtime";
5
+ export declare const SUBAGENT_CONTRACT_VERSION: 1;
6
+ export type SubagentFingerprint = Fingerprint;
7
+ export { FINGERPRINT_PREFIX as SUBAGENT_FINGERPRINT_PREFIX } from "@zihanw/pi-subagent-runtime";
8
+ export type SubagentDiagnosticLevel = DiagnosticLevel;
9
+ export type SubagentDiagnostic = Diagnostic;
10
+ export type SubagentMediaReference = MediaReference;
11
+ export type SubagentAccessLevel = AccessLevel;
12
+ export type SubagentWorkspaceMode = WorkspaceMode;
13
+ export type SubagentNetworkPolicy = NetworkPolicy;
14
+ export type SubagentExecutionBoundary = ExecutionBoundary;
15
+ export type SubagentWorkspaceRequest = WorkspaceRequest;
16
+ export type SubagentWorkingDirectoryRequest = WorkingDirectoryRequest;
17
+ export type SubagentAccessRequest = AccessRequest;
18
+ export type SubagentLimitName = LimitName;
19
+ export type SubagentLimitEnforcementPreference = LimitRequirementLevel;
20
+ export type SubagentLimitRequirement = LimitRequirement;
21
+ export type SubagentLimitRequest = LimitRequest;
22
+ export type SubagentToolEffect = ToolEffect;
23
+ export type SubagentBackendTool = BackendTool;
24
+ export type SubagentAccessCapabilities = AccessCapabilities;
25
+ export type SubagentLimitEnforcement = LimitEnforcement;
26
+ export type SubagentMountMapping = MountMapping;
27
+ export type SubagentEnforcedLimit = EnforcedLimit;
28
+ export type SubagentLimitReceipt = LimitReceipt;
29
+ export type SubagentPreparedMessageRole = PreparedMessageRole;
30
+ export type SubagentPreparedContentPart = PreparedContentPart;
31
+ export type SubagentPromptRuntimeSkill = PromptRuntimeSkill;
32
+ export type SubagentPromptRuntimeOptions = PromptRuntimeOptions;
33
+ export type SubagentUsage = RunUsage;
34
+ export type SubagentError = RunError;
35
+ export type SubagentAccessReceipt = AccessReceipt;
36
+ export type SubagentPreparationRuntime = PromptRuntime;
37
+ export type SubagentBackendCapabilities = BackendCapabilities & {
38
+ traceInspection: boolean;
39
+ artifactRetention: boolean;
40
+ };
41
+ export type SubagentBackendDescriptor = Omit<BackendDescriptor, "capabilities"> & {
42
+ capabilities: SubagentBackendCapabilities;
43
+ };
44
+ export type SubagentPreparedMessage = PreparedMessage & {
45
+ protectedTask?: boolean;
46
+ source?: "selected-context" | "prompt-stack" | "delegated-task";
47
+ };
48
+ export interface SubagentTaskInput {
49
+ text: string;
50
+ media?: SubagentMediaReference[];
51
+ }
52
+ export type SubagentContextItemKind = "summary" | "user-excerpt" | "assistant-excerpt" | "tool-result-excerpt" | "resource-excerpt";
53
+ export interface SubagentContextProvenance {
54
+ source: string;
55
+ reference?: string;
56
+ }
57
+ export interface SubagentContextItem {
58
+ id: string;
59
+ kind: SubagentContextItemKind;
60
+ text: string;
61
+ required?: boolean;
62
+ provenance: SubagentContextProvenance;
63
+ }
64
+ export interface SubagentSelectedContext {
65
+ maxBytes: number;
66
+ items: SubagentContextItem[];
67
+ }
68
+ export interface AgentRequest {
69
+ schemaVersion: typeof SUBAGENT_CONTRACT_VERSION;
70
+ requestId: string;
71
+ profileId: string;
72
+ expectedProfileFingerprint?: SubagentFingerprint;
73
+ input: SubagentTaskInput;
74
+ selectedContext?: SubagentSelectedContext;
75
+ access: SubagentAccessRequest;
76
+ limits: SubagentLimitRequest;
77
+ resultProjection: {
78
+ maxChars: number;
79
+ };
80
+ parent: {
81
+ runId?: string;
82
+ sessionId?: string;
83
+ depth: number;
84
+ maxDepth: number;
85
+ };
86
+ remoteEgressConsent: boolean;
87
+ }
88
+ export type SubagentDependencyKind = "macro" | "slot";
89
+ export interface SubagentPromptDependency {
90
+ kind: SubagentDependencyKind;
91
+ name: string;
92
+ identity: string;
93
+ source?: string;
94
+ }
95
+ export interface AgentProfileSnapshot {
96
+ schemaVersion: typeof SUBAGENT_CONTRACT_VERSION;
97
+ profile: AgentProfile;
98
+ promptStack: PromptStack | null;
99
+ dependencies: SubagentPromptDependency[];
100
+ profileFingerprint: SubagentFingerprint;
101
+ promptStackFingerprint: SubagentFingerprint | null;
102
+ }
103
+ export interface SubagentToolNegotiationResult {
104
+ effectiveToolIds: string[];
105
+ effectiveToolNames: string[];
106
+ stackSelectedToolNames: string[];
107
+ unmatchedAllowPatterns: string[];
108
+ diagnostics: SubagentDiagnostic[];
109
+ }
110
+ export interface SubagentContextBudgetReceipt {
111
+ maxBytes: number;
112
+ includedBytes: number;
113
+ includedItemIds: string[];
114
+ omittedItemIds: string[];
115
+ }
116
+ export interface BackendPreflightAccepted {
117
+ status: "accepted";
118
+ preflightId: string;
119
+ backend: SubagentBackendDescriptor;
120
+ model: AgentProfileModelReference;
121
+ thinkingLevel: ThinkingLevel;
122
+ toolCatalog: SubagentBackendTool[];
123
+ access: SubagentAccessReceipt;
124
+ limits: SubagentLimitReceipt;
125
+ promptRuntime?: SubagentPreparationRuntime;
126
+ diagnostics: SubagentDiagnostic[];
127
+ }
128
+ export interface BackendPreflightRejected {
129
+ status: "rejected";
130
+ preflightId: string;
131
+ backend: SubagentBackendDescriptor;
132
+ diagnostics: SubagentDiagnostic[];
133
+ }
134
+ export type BackendPreflightResult = BackendPreflightAccepted | BackendPreflightRejected;
135
+ export interface SubagentPreparationBaseInput {
136
+ request: AgentRequest;
137
+ snapshot: AgentProfileSnapshot;
138
+ preflight: BackendPreflightAccepted;
139
+ }
140
+ export interface SubagentPreparationInput extends SubagentPreparationBaseInput {
141
+ runtime: SubagentPreparationRuntime;
142
+ }
143
+ export interface SubagentPreparationOutput {
144
+ systemPrompt: string;
145
+ messages: SubagentPreparedMessage[];
146
+ toolNegotiation: SubagentToolNegotiationResult;
147
+ contextBudget?: SubagentContextBudgetReceipt;
148
+ diagnostics: SubagentDiagnostic[];
149
+ }
150
+ export interface SubagentPreparationResult {
151
+ runtime: SubagentPreparationRuntime;
152
+ preparation: SubagentPreparationOutput;
153
+ }
154
+ export type SubagentHostPlanPreparer = (input: SubagentPreparationInput) => Promise<SubagentPreparationOutput> | SubagentPreparationOutput;
155
+ export interface AgentExecutionPlan {
156
+ schemaVersion: typeof SUBAGENT_CONTRACT_VERSION;
157
+ runId: string;
158
+ requestId: string;
159
+ backendId: string;
160
+ preflightId: string;
161
+ preflight: BackendPreflightAccepted;
162
+ profile: AgentProfileSnapshot;
163
+ model: AgentProfileModelReference;
164
+ thinkingLevel: ThinkingLevel;
165
+ systemPrompt: string;
166
+ messages: SubagentPreparedMessage[];
167
+ effectiveToolIds: string[];
168
+ access: SubagentAccessReceipt;
169
+ limits: SubagentLimitReceipt;
170
+ contextBudget?: SubagentContextBudgetReceipt;
171
+ resultProjection: AgentRequest["resultProjection"];
172
+ promptRuntimeFingerprint: SubagentFingerprint;
173
+ /** Runtime-issued fingerprint of the sealed system prompt and ordered messages. */
174
+ conversationFingerprint: SubagentFingerprint;
175
+ /**
176
+ * Runtime-issued fingerprint binding the sealed conversation to the
177
+ * accepted backend, preflight, tools, and limits. The host never computes
178
+ * this value; it displays and propagates the sealed fingerprint so approval
179
+ * and execution stay bound to the exact plan the runtime sealed.
180
+ */
181
+ executionFingerprint: SubagentFingerprint;
182
+ }
183
+ export type SubagentArtifactLifetime = "run" | "session" | "persistent";
184
+ export type SubagentArtifactAuthorization = "read" | "write";
185
+ export interface SubagentArtifactReference {
186
+ id: string;
187
+ workspaceNamespace: string;
188
+ path: string;
189
+ authorization: SubagentArtifactAuthorization;
190
+ lifetime: SubagentArtifactLifetime;
191
+ cleanup: "backend" | "host" | "user";
192
+ }
193
+ export interface SubagentTraceReference {
194
+ handle: string;
195
+ backendId: string;
196
+ authorizationScope: string;
197
+ expiresAt?: string;
198
+ }
199
+ export interface AgentResponseCommon {
200
+ schemaVersion: typeof SUBAGENT_CONTRACT_VERSION;
201
+ requestId: string;
202
+ runId: string;
203
+ backendId: string;
204
+ profileFingerprint: SubagentFingerprint;
205
+ executionFingerprint: SubagentFingerprint;
206
+ model: AgentProfileModelReference;
207
+ effectiveToolIds: string[];
208
+ enforcement: {
209
+ access: SubagentAccessReceipt;
210
+ limits: SubagentLimitReceipt;
211
+ };
212
+ durationMs: number;
213
+ artifacts: SubagentArtifactReference[];
214
+ trace?: SubagentTraceReference;
215
+ usage?: SubagentUsage;
216
+ }
217
+ export interface AgentResponseCompleted extends AgentResponseCommon {
218
+ status: "completed";
219
+ output?: {
220
+ text: string;
221
+ partial: false;
222
+ };
223
+ }
224
+ export interface AgentResponseFailed extends AgentResponseCommon {
225
+ status: "failed";
226
+ error: SubagentError;
227
+ output?: {
228
+ text: string;
229
+ partial: true;
230
+ };
231
+ }
232
+ export interface AgentResponseCancelled extends AgentResponseCommon {
233
+ status: "cancelled";
234
+ reason: string;
235
+ output?: {
236
+ text: string;
237
+ partial: true;
238
+ };
239
+ }
240
+ export interface AgentResponseTimedOut extends AgentResponseCommon {
241
+ status: "timed-out";
242
+ reason: string;
243
+ enforcedTimeoutMs: number;
244
+ output?: {
245
+ text: string;
246
+ partial: true;
247
+ };
248
+ }
249
+ export interface AgentResponseLimitReached extends AgentResponseCommon {
250
+ status: "limit-reached";
251
+ reachedLimit: SubagentLimitName;
252
+ output?: {
253
+ text: string;
254
+ partial: true;
255
+ };
256
+ }
257
+ export type AgentResponse = AgentResponseCompleted | AgentResponseFailed | AgentResponseCancelled | AgentResponseTimedOut | AgentResponseLimitReached;
258
+ export interface SubagentContextBudgetResult {
259
+ items: SubagentContextItem[];
260
+ receipt: SubagentContextBudgetReceipt;
261
+ diagnostics: SubagentDiagnostic[];
262
+ }
263
+ export interface SubagentInitialMessagesResult {
264
+ messages: SubagentPreparedMessage[];
265
+ contextBudget?: SubagentContextBudgetReceipt;
266
+ diagnostics: SubagentDiagnostic[];
267
+ }
268
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/subagent/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export const SUBAGENT_CONTRACT_VERSION = 1;
2
+ export { FINGERPRINT_PREFIX as SUBAGENT_FINGERPRINT_PREFIX } from "@zihanw/pi-subagent-runtime";
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/subagent/types.ts"],"names":[],"mappings":"AAuCA,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAU,CAAC;AAcpD,OAAO,EAAE,kBAAkB,IAAI,2BAA2B,EAAE,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { FINGERPRINT_PATTERN, LIMIT_NAMES, OPAQUE_ID_PATTERN, error, hasErrors, isFingerprint, isRecord, isSafeRelativePath, validateAccessEnforcement } from "@zihanw/pi-subagent-runtime";
2
+ import type { SubagentDiagnostic, SubagentPreparationRuntime } from "./types.ts";
3
+ export { FINGERPRINT_PATTERN, LIMIT_NAMES as SUBAGENT_LIMIT_NAMES, OPAQUE_ID_PATTERN, error, hasErrors, hasErrors as hasSubagentErrors, isFingerprint, isRecord, isSafeRelativePath, validateAccessEnforcement, };
4
+ export declare const NAMESPACE_PATTERN: RegExp;
5
+ export declare function validateAccessRequest(value: unknown, path: string, diagnostics: SubagentDiagnostic[]): void;
6
+ export declare function validateLimitRequest(value: unknown, path: string, diagnostics: SubagentDiagnostic[]): void;
7
+ export declare function validateLimitReceipt(value: unknown, path: string, diagnostics: SubagentDiagnostic[]): void;
8
+ export declare function validateBackendDescriptor(value: Record<string, unknown>, path: string, diagnostics: SubagentDiagnostic[]): void;
9
+ export declare function validatePreparationRuntime(value: unknown, path: string, diagnostics: SubagentDiagnostic[], expectedFidelity?: SubagentPreparationRuntime["fidelity"]): void;
10
+ export declare function validateMediaReference(value: unknown, path: string, diagnostics: SubagentDiagnostic[]): void;
11
+ export declare function validateSelectedContext(value: unknown, path: string, diagnostics: SubagentDiagnostic[]): SubagentDiagnostic[];
12
+ export declare function validateToolCatalog(value: readonly unknown[], diagnostics: SubagentDiagnostic[]): void;
13
+ /**
14
+ * Host access-receipt validation. The portable runtime validator intentionally
15
+ * checks less: the host additionally enforces mount uniqueness, access-level
16
+ * consistency, and the isolation claims a receipt may make for its execution
17
+ * boundary, because these cross-checks are the honesty terms of the host
18
+ * contract (a shared-user boundary must never claim OS isolation).
19
+ */
20
+ export declare function validateAccessReceipt(value: unknown, path: string, diagnostics: SubagentDiagnostic[]): void;
21
+ export declare function validateAccessCapabilities(value: Record<string, unknown>, path: string, diagnostics: SubagentDiagnostic[]): void;
22
+ export declare function validatePreparedMessage(value: unknown, path: string, diagnostics: SubagentDiagnostic[]): void;
23
+ export declare function validateContextBudgetReceipt(value: unknown, path: string, diagnostics: SubagentDiagnostic[]): void;
24
+ export declare function validateUniqueStringArray(value: readonly unknown[], path: string, diagnostics: SubagentDiagnostic[]): void;
25
+ export declare function validateDiagnosticArray(value: readonly unknown[], path: string, diagnostics: SubagentDiagnostic[]): void;
26
+ export declare function validateUsage(value: unknown, path: string, diagnostics: SubagentDiagnostic[]): void;
27
+ export declare function validateModelReference(value: unknown, path: string, diagnostics: SubagentDiagnostic[]): void;
28
+ export declare function validateOpaqueId(value: unknown, path: string, diagnostics: SubagentDiagnostic[]): void;
29
+ export declare function validateNamespace(value: unknown, path: string, diagnostics: SubagentDiagnostic[]): void;
30
+ export declare function validateFingerprint(value: unknown, path: string, diagnostics: SubagentDiagnostic[]): void;
31
+ export declare function isIsoDate(value: unknown): boolean;
32
+ export declare function isPositiveInteger(value: unknown): value is number;
33
+ export declare function isNonNegativeInteger(value: unknown): value is number;
34
+ export declare function isNonNegativeFinite(value: unknown): value is number;
35
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/subagent/validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,314 @@
1
+ import { FINGERPRINT_PATTERN, LIMIT_NAMES, OPAQUE_ID_PATTERN, error, hasErrors, isFingerprint, isRecord, isSafeRelativePath, validateAccessEnforcement, validateAccessRequest as validatePortableAccessRequest, validateBackendDescriptor as validatePortableBackendDescriptor, validateLimitReceipt as validatePortableLimitReceipt, validateLimitRequest as validatePortableLimitRequest, validatePromptRuntime as validatePortablePromptRuntime, } from "@zihanw/pi-subagent-runtime";
2
+ // ---------------------------------------------------------------------------
3
+ // Portable leaves owned by @zihanw/pi-subagent-runtime core.
4
+ //
5
+ // The runtime package is the single source of truth for validators over the
6
+ // portable execution contract. This module re-exports the identical helpers
7
+ // and adapts the runtime's returning-style validators to the collecting-style
8
+ // signatures the 0.4 host contract always used. Only host-specific artifacts
9
+ // (selected context, context budgets, media references, usage, artifacts,
10
+ // traces, and the richer host access-receipt checks) keep local
11
+ // implementations below.
12
+ // ---------------------------------------------------------------------------
13
+ export { FINGERPRINT_PATTERN, LIMIT_NAMES as SUBAGENT_LIMIT_NAMES, OPAQUE_ID_PATTERN, error, hasErrors, hasErrors as hasSubagentErrors, isFingerprint, isRecord, isSafeRelativePath, validateAccessEnforcement, };
14
+ export const NAMESPACE_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
15
+ export function validateAccessRequest(value, path, diagnostics) {
16
+ diagnostics.push(...validatePortableAccessRequest(value, path));
17
+ }
18
+ export function validateLimitRequest(value, path, diagnostics) {
19
+ diagnostics.push(...validatePortableLimitRequest(value, path));
20
+ }
21
+ export function validateLimitReceipt(value, path, diagnostics) {
22
+ diagnostics.push(...validatePortableLimitReceipt(value, path));
23
+ }
24
+ export function validateBackendDescriptor(value, path, diagnostics) {
25
+ diagnostics.push(...repath(validatePortableBackendDescriptor(value), path));
26
+ // Host-only capability booleans the portable descriptor does not carry.
27
+ if (isRecord(value.capabilities)) {
28
+ for (const field of ["traceInspection", "artifactRetention"]) {
29
+ if (typeof value.capabilities[field] !== "boolean")
30
+ diagnostics.push(error("backend.boolean-capability", `${field} must be boolean.`, `${path}.capabilities.${field}`));
31
+ }
32
+ }
33
+ }
34
+ export function validatePreparationRuntime(value, path, diagnostics, expectedFidelity) {
35
+ diagnostics.push(...repath(validatePortablePromptRuntime(value, expectedFidelity), path));
36
+ }
37
+ // ---------------------------------------------------------------------------
38
+ // Host-specific validators with no portable counterpart.
39
+ // ---------------------------------------------------------------------------
40
+ export function validateMediaReference(value, path, diagnostics) {
41
+ if (!isRecord(value)) {
42
+ diagnostics.push(error("request.media-item", "Media reference must be an object.", path));
43
+ return;
44
+ }
45
+ validateOpaqueId(value.id, `${path}.id`, diagnostics);
46
+ if (value.kind !== "image")
47
+ diagnostics.push(error("request.media-kind", "Only image media is supported in v1.", `${path}.kind`));
48
+ if (typeof value.mimeType !== "string" || !/^image\/[A-Za-z0-9.+-]+$/.test(value.mimeType))
49
+ diagnostics.push(error("request.media-mime", "mimeType must be an image MIME type.", `${path}.mimeType`));
50
+ validateFingerprint(value.digest, `${path}.digest`, diagnostics);
51
+ validateOpaqueId(value.resourceHandle, `${path}.resourceHandle`, diagnostics);
52
+ }
53
+ export function validateSelectedContext(value, path, diagnostics) {
54
+ if (!isRecord(value)) {
55
+ diagnostics.push(error("context.type", "selectedContext must be an object.", path));
56
+ return diagnostics;
57
+ }
58
+ if (!isPositiveInteger(value.maxBytes))
59
+ diagnostics.push(error("context.max-bytes", "maxBytes must be a positive integer.", `${path}.maxBytes`));
60
+ if (!Array.isArray(value.items)) {
61
+ diagnostics.push(error("context.items", "items must be an array.", `${path}.items`));
62
+ return diagnostics;
63
+ }
64
+ const ids = new Set();
65
+ value.items.forEach((item, index) => {
66
+ const itemPath = `${path}.items[${index}]`;
67
+ if (!isRecord(item)) {
68
+ diagnostics.push(error("context.item", "Context item must be an object.", itemPath));
69
+ return;
70
+ }
71
+ validateOpaqueId(item.id, `${itemPath}.id`, diagnostics);
72
+ if (typeof item.id === "string" && ids.has(item.id))
73
+ diagnostics.push(error("context.duplicate-id", `Duplicate context item id: ${item.id}`, `${itemPath}.id`));
74
+ if (typeof item.id === "string")
75
+ ids.add(item.id);
76
+ if (!["summary", "user-excerpt", "assistant-excerpt", "tool-result-excerpt", "resource-excerpt"].includes(String(item.kind)))
77
+ diagnostics.push(error("context.kind", "Unsupported context item kind.", `${itemPath}.kind`));
78
+ if (typeof item.text !== "string" || !item.text.trim())
79
+ diagnostics.push(error("context.text", "Context item text must not be empty.", `${itemPath}.text`));
80
+ if (item.required !== undefined && typeof item.required !== "boolean")
81
+ diagnostics.push(error("context.required", "required must be boolean.", `${itemPath}.required`));
82
+ if (!isRecord(item.provenance) || typeof item.provenance.source !== "string" || !item.provenance.source.trim())
83
+ diagnostics.push(error("context.provenance", "Context item provenance.source is required.", `${itemPath}.provenance`));
84
+ });
85
+ return diagnostics;
86
+ }
87
+ export function validateToolCatalog(value, diagnostics) {
88
+ const ids = new Set();
89
+ const names = new Set();
90
+ value.forEach((tool, index) => {
91
+ if (!isRecord(tool))
92
+ return diagnostics.push(error("tools.catalog-entry", "Tool catalog entry must be an object.", `toolCatalog[${index}]`));
93
+ validateOpaqueId(tool.id, `toolCatalog[${index}].id`, diagnostics);
94
+ validateOpaqueId(tool.name, `toolCatalog[${index}].name`, diagnostics);
95
+ if (typeof tool.id === "string" && ids.has(tool.id))
96
+ diagnostics.push(error("tools.duplicate-id", `Duplicate tool id: ${tool.id}`, `toolCatalog[${index}].id`));
97
+ if (typeof tool.name === "string" && names.has(tool.name))
98
+ diagnostics.push(error("tools.duplicate-name", `Duplicate tool name: ${tool.name}`, `toolCatalog[${index}].name`));
99
+ if (typeof tool.id === "string")
100
+ ids.add(tool.id);
101
+ if (typeof tool.name === "string")
102
+ names.add(tool.name);
103
+ if (!Array.isArray(tool.effects) || tool.effects.some((effect) => !["filesystem-read", "filesystem-write", "process", "network"].includes(String(effect))))
104
+ diagnostics.push(error("tools.effects", "Tool effects must be a valid effect array.", `toolCatalog[${index}].effects`));
105
+ });
106
+ }
107
+ /**
108
+ * Host access-receipt validation. The portable runtime validator intentionally
109
+ * checks less: the host additionally enforces mount uniqueness, access-level
110
+ * consistency, and the isolation claims a receipt may make for its execution
111
+ * boundary, because these cross-checks are the honesty terms of the host
112
+ * contract (a shared-user boundary must never claim OS isolation).
113
+ */
114
+ export function validateAccessReceipt(value, path, diagnostics) {
115
+ if (!isRecord(value)) {
116
+ diagnostics.push(error("access-receipt.type", "Access receipt must be an object.", path));
117
+ return;
118
+ }
119
+ if (!["none", "read-only", "workspace-write"].includes(String(value.level)))
120
+ diagnostics.push(error("access-receipt.level", "Invalid access receipt level.", `${path}.level`));
121
+ if (!Array.isArray(value.mounts))
122
+ diagnostics.push(error("access-receipt.mounts", "Access receipt mounts must be an array.", `${path}.mounts`));
123
+ else {
124
+ const handles = new Set();
125
+ const mountIds = new Set();
126
+ value.mounts.forEach((mount, index) => {
127
+ if (!isRecord(mount))
128
+ return diagnostics.push(error("access-receipt.mount", "Mount mapping must be an object.", `${path}.mounts[${index}]`));
129
+ validateOpaqueId(mount.workspaceHandle, `${path}.mounts[${index}].workspaceHandle`, diagnostics);
130
+ validateOpaqueId(mount.mountId, `${path}.mounts[${index}].mountId`, diagnostics);
131
+ if (mount.mode !== "read-only" && mount.mode !== "read-write")
132
+ diagnostics.push(error("access-receipt.mount-mode", "Mount mode must be read-only or read-write.", `${path}.mounts[${index}].mode`));
133
+ if (typeof mount.workspaceHandle === "string" && handles.has(mount.workspaceHandle))
134
+ diagnostics.push(error("access-receipt.duplicate-workspace", `Duplicate workspace mapping: ${mount.workspaceHandle}`, `${path}.mounts[${index}].workspaceHandle`));
135
+ if (typeof mount.mountId === "string" && mountIds.has(mount.mountId))
136
+ diagnostics.push(error("access-receipt.duplicate-mount", `Duplicate mount id: ${mount.mountId}`, `${path}.mounts[${index}].mountId`));
137
+ if (typeof mount.workspaceHandle === "string")
138
+ handles.add(mount.workspaceHandle);
139
+ if (typeof mount.mountId === "string")
140
+ mountIds.add(mount.mountId);
141
+ });
142
+ if (value.level === "none" && value.mounts.length > 0)
143
+ diagnostics.push(error("access-receipt.none-mounts", "Access none cannot produce mount mappings.", `${path}.mounts`));
144
+ if (value.level === "read-only" && value.mounts.some((mount) => isRecord(mount) && mount.mode === "read-write"))
145
+ diagnostics.push(error("access-receipt.read-only-write", "Read-only access cannot produce a read-write mount.", `${path}.mounts`));
146
+ if (value.level === "workspace-write" && !value.mounts.some((mount) => isRecord(mount) && mount.mode === "read-write"))
147
+ diagnostics.push(error("access-receipt.write-missing", "workspace-write receipt requires a read-write mount.", `${path}.mounts`));
148
+ if (value.workingDirectory !== undefined) {
149
+ if (!isRecord(value.workingDirectory))
150
+ diagnostics.push(error("access-receipt.cwd", "workingDirectory must be an object.", `${path}.workingDirectory`));
151
+ else {
152
+ if (!mountIds.has(String(value.workingDirectory.mountId)))
153
+ diagnostics.push(error("access-receipt.cwd-mount", "workingDirectory must reference a receipt mount.", `${path}.workingDirectory.mountId`));
154
+ if (!isSafeRelativePath(value.workingDirectory.path, true))
155
+ diagnostics.push(error("access-receipt.cwd-path", "workingDirectory path must be normalized and relative.", `${path}.workingDirectory.path`));
156
+ }
157
+ }
158
+ }
159
+ if (value.network !== "deny" && value.network !== "allow")
160
+ diagnostics.push(error("access-receipt.network", "Invalid access receipt network policy.", `${path}.network`));
161
+ if (typeof value.process !== "boolean")
162
+ diagnostics.push(error("access-receipt.process", "Access receipt process must be boolean.", `${path}.process`));
163
+ if (value.process === true && value.level !== "workspace-write")
164
+ diagnostics.push(error("access-receipt.process-level", "Process access requires workspace-write.", `${path}.process`));
165
+ if (value.executionBoundary !== undefined && value.executionBoundary !== "isolated" && value.executionBoundary !== "shared-user") {
166
+ diagnostics.push(error("access-receipt.boundary", "executionBoundary must be isolated or shared-user.", `${path}.executionBoundary`));
167
+ }
168
+ const executionBoundary = value.executionBoundary ?? "isolated";
169
+ if (!isRecord(value.enforcement))
170
+ diagnostics.push(error("access-receipt.enforcement", "Access enforcement receipt is required.", `${path}.enforcement`));
171
+ else {
172
+ validateAccessCapabilities(value.enforcement, `${path}.enforcement`, diagnostics);
173
+ if (executionBoundary === "shared-user") {
174
+ for (const field of ["readOnlyMountIsolation", "readWriteMountIsolation", "symlinkSafeContainment", "processIsolation", "agentNetworkIsolation"]) {
175
+ if (value.enforcement[field] === true)
176
+ diagnostics.push(error("access-receipt.shared-user-claim", `A shared-user boundary cannot claim ${field}.`, `${path}.enforcement.${field}`));
177
+ }
178
+ }
179
+ if (executionBoundary === "isolated" && value.level === "read-only" && (!value.enforcement.readOnlyMountIsolation || !value.enforcement.symlinkSafeContainment))
180
+ diagnostics.push(error("access-receipt.read-isolation", "Isolated read-only access requires mount isolation and symlink-safe containment.", `${path}.enforcement`));
181
+ if (value.level === "workspace-write" && (!value.enforcement.readWriteMountIsolation || !value.enforcement.symlinkSafeContainment))
182
+ diagnostics.push(error("access-receipt.write-isolation", "Workspace-write receipt requires write isolation and symlink-safe containment.", `${path}.enforcement`));
183
+ if (value.process === true && !value.enforcement.processIsolation)
184
+ diagnostics.push(error("access-receipt.process-isolation", "Process receipt requires process isolation.", `${path}.enforcement.processIsolation`));
185
+ if (value.network === "deny" && !value.enforcement.agentNetworkIsolation)
186
+ diagnostics.push(error("access-receipt.network-isolation", "Denied network receipt requires agent network isolation.", `${path}.enforcement.agentNetworkIsolation`));
187
+ }
188
+ if (value.level === "none" && value.workingDirectory !== undefined)
189
+ diagnostics.push(error("access-receipt.none-cwd", "Access none cannot produce a workingDirectory.", `${path}.workingDirectory`));
190
+ }
191
+ export function validateAccessCapabilities(value, path, diagnostics) {
192
+ for (const field of [
193
+ "readOnlyMountIsolation", "readWriteMountIsolation", "symlinkSafeContainment", "processIsolation", "agentNetworkIsolation",
194
+ ]) {
195
+ if (typeof value[field] !== "boolean")
196
+ diagnostics.push(error("access-capability.boolean", `${field} must be boolean.`, `${path}.${field}`));
197
+ }
198
+ }
199
+ export function validatePreparedMessage(value, path, diagnostics) {
200
+ if (!isRecord(value)) {
201
+ diagnostics.push(error("plan.message", "Prepared message must be an object.", path));
202
+ return;
203
+ }
204
+ if (!["user", "assistant", "custom"].includes(String(value.role)))
205
+ diagnostics.push(error("plan.message-role", "Unsupported prepared message role.", `${path}.role`));
206
+ if (!Array.isArray(value.content) || value.content.length === 0) {
207
+ diagnostics.push(error("plan.message-content", "Prepared message content must be a non-empty array.", `${path}.content`));
208
+ return;
209
+ }
210
+ value.content.forEach((part, index) => {
211
+ if (!isRecord(part))
212
+ return diagnostics.push(error("plan.content-part", "Content part must be an object.", `${path}.content[${index}]`));
213
+ if (part.type === "text") {
214
+ if (typeof part.text !== "string")
215
+ diagnostics.push(error("plan.text-part", "Text content requires text.", `${path}.content[${index}].text`));
216
+ }
217
+ else if (part.type === "media") {
218
+ validateOpaqueId(part.mediaId, `${path}.content[${index}].mediaId`, diagnostics);
219
+ if (typeof part.mimeType !== "string" || !part.mimeType.includes("/"))
220
+ diagnostics.push(error("plan.media-mime", "Media content requires mimeType.", `${path}.content[${index}].mimeType`));
221
+ validateFingerprint(part.digest, `${path}.content[${index}].digest`, diagnostics);
222
+ if (part.backendResourceId !== undefined)
223
+ validateOpaqueId(part.backendResourceId, `${path}.content[${index}].backendResourceId`, diagnostics);
224
+ }
225
+ else
226
+ diagnostics.push(error("plan.content-type", "Unsupported prepared content part type.", `${path}.content[${index}].type`));
227
+ });
228
+ if (value.protectedTask !== undefined && typeof value.protectedTask !== "boolean")
229
+ diagnostics.push(error("plan.protected-flag", "protectedTask must be boolean.", `${path}.protectedTask`));
230
+ }
231
+ export function validateContextBudgetReceipt(value, path, diagnostics) {
232
+ if (!isRecord(value)) {
233
+ diagnostics.push(error("context-receipt.type", "Context budget receipt must be an object.", path));
234
+ return;
235
+ }
236
+ if (!isPositiveInteger(value.maxBytes))
237
+ diagnostics.push(error("context-receipt.max", "maxBytes must be a positive integer.", `${path}.maxBytes`));
238
+ if (!isNonNegativeInteger(value.includedBytes) || (isPositiveInteger(value.maxBytes) && value.includedBytes > value.maxBytes))
239
+ diagnostics.push(error("context-receipt.bytes", "includedBytes must be non-negative and no greater than maxBytes.", `${path}.includedBytes`));
240
+ for (const field of ["includedItemIds", "omittedItemIds"]) {
241
+ if (!Array.isArray(value[field]))
242
+ diagnostics.push(error("context-receipt.ids", `${field} must be an array.`, `${path}.${field}`));
243
+ else
244
+ validateUniqueStringArray(value[field], `${path}.${field}`, diagnostics);
245
+ }
246
+ }
247
+ export function validateUniqueStringArray(value, path, diagnostics) {
248
+ const seen = new Set();
249
+ value.forEach((item, index) => {
250
+ if (typeof item !== "string")
251
+ diagnostics.push(error("array.string", "Expected a string.", `${path}[${index}]`));
252
+ else if (seen.has(item))
253
+ diagnostics.push(error("array.duplicate", `Duplicate value: ${item}`, `${path}[${index}]`));
254
+ else
255
+ seen.add(item);
256
+ });
257
+ }
258
+ export function validateDiagnosticArray(value, path, diagnostics) {
259
+ value.forEach((item, index) => {
260
+ if (!isRecord(item) || !["error", "warning", "info"].includes(String(item.level)) || typeof item.code !== "string" || typeof item.message !== "string")
261
+ diagnostics.push(error("diagnostic.invalid", "Diagnostic requires level, code, and message.", `${path}[${index}]`));
262
+ });
263
+ }
264
+ export function validateUsage(value, path, diagnostics) {
265
+ if (!isRecord(value)) {
266
+ diagnostics.push(error("usage.type", "usage must be an object.", path));
267
+ return;
268
+ }
269
+ if (value.tokens !== undefined) {
270
+ if (!isRecord(value.tokens) || !isNonNegativeInteger(value.tokens.input) || !isNonNegativeInteger(value.tokens.output) || !isNonNegativeInteger(value.tokens.total))
271
+ diagnostics.push(error("usage.tokens", "Token usage values must be non-negative integers.", `${path}.tokens`));
272
+ else if (value.tokens.total < value.tokens.input + value.tokens.output)
273
+ diagnostics.push(error("usage.token-total", "Token total cannot be less than input + output.", `${path}.tokens.total`));
274
+ }
275
+ if (value.cost !== undefined && (!isRecord(value.cost) || !isNonNegativeFinite(value.cost.amount) || typeof value.cost.currency !== "string" || !/^[A-Z]{3}$/.test(value.cost.currency)))
276
+ diagnostics.push(error("usage.cost", "Cost requires a non-negative amount and ISO 4217 currency code.", `${path}.cost`));
277
+ }
278
+ export function validateModelReference(value, path, diagnostics) {
279
+ if (!isRecord(value) || typeof value.provider !== "string" || !value.provider.trim() || typeof value.id !== "string" || !value.id.trim())
280
+ diagnostics.push(error("model.reference", "Model reference requires provider and id.", path));
281
+ }
282
+ export function validateOpaqueId(value, path, diagnostics) {
283
+ if (typeof value !== "string" || !OPAQUE_ID_PATTERN.test(value))
284
+ diagnostics.push(error("id.invalid", "Expected an opaque id using letters, numbers, dot, underscore, colon, or hyphen (max 128).", path));
285
+ }
286
+ export function validateNamespace(value, path, diagnostics) {
287
+ if (typeof value !== "string" || !NAMESPACE_PATTERN.test(value))
288
+ diagnostics.push(error("namespace.invalid", "Expected a namespace using letters, numbers, dot, underscore, or hyphen (max 128).", path));
289
+ }
290
+ export function validateFingerprint(value, path, diagnostics) {
291
+ if (!isFingerprint(value))
292
+ diagnostics.push(error("fingerprint.invalid", "Expected sha256:v1 followed by 64 lowercase hex characters.", path));
293
+ }
294
+ export function isIsoDate(value) {
295
+ return typeof value === "string" && !Number.isNaN(Date.parse(value)) && new Date(value).toISOString() === value;
296
+ }
297
+ export function isPositiveInteger(value) {
298
+ return Number.isSafeInteger(value) && value > 0;
299
+ }
300
+ export function isNonNegativeInteger(value) {
301
+ return Number.isSafeInteger(value) && value >= 0;
302
+ }
303
+ export function isNonNegativeFinite(value) {
304
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
305
+ }
306
+ /** Remap a runtime-core diagnostic rooted at "$" onto the caller's path. */
307
+ function repath(diagnostics, path) {
308
+ return diagnostics.map((diagnostic) => {
309
+ if (!diagnostic.path || !diagnostic.path.startsWith("$"))
310
+ return diagnostic;
311
+ return { ...diagnostic, path: `${path}${diagnostic.path.slice(1)}` };
312
+ });
313
+ }
314
+ //# sourceMappingURL=validation.js.map