@lota-sdk/shared 0.1.15 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lota-sdk/shared",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -25,7 +25,7 @@
25
25
  "registry": "https://registry.npmjs.org/"
26
26
  },
27
27
  "dependencies": {
28
- "ai": "^6.0.134",
28
+ "ai": "^6.0.137",
29
29
  "zod": "^4.3.6"
30
30
  }
31
31
  }
@@ -0,0 +1,34 @@
1
+ export const OPENAI_REASONING_MODEL_ID = 'openai/gpt-5.4' as const
2
+
3
+ export const OPENROUTER_TEAM_AGENT_MODEL_ID = 'openrouter/google/gemini-3.1-pro-preview' as const
4
+ export const OPENROUTER_STRUCTURED_HELPER_MODEL_ID = 'openrouter/google/gemini-3-flash-preview:exacto' as const
5
+ export const OPENROUTER_DELEGATED_REASONING_MODEL_ID = 'openrouter/google/gemini-3-flash-preview:exacto' as const
6
+ export const OPENROUTER_WEB_RESEARCH_MODEL_ID = 'openrouter/stepfun/step-3.5-flash' as const
7
+ export const OPENROUTER_FAST_REASONING_MODEL_ID = 'openrouter/openai/gpt-oss-120b:nitro' as const
8
+ export const OPENROUTER_STRUCTURED_REASONING_MODEL_ID = 'openrouter/openai/gpt-oss-120b:exacto' as const
9
+
10
+ export const BIFROST_REASONING_SUMMARY_LEVEL = 'detailed' as const
11
+
12
+ export const OPENAI_HIGH_REASONING_PROVIDER_OPTIONS = {
13
+ openai: { forceReasoning: true, reasoningEffort: 'high', reasoningSummary: BIFROST_REASONING_SUMMARY_LEVEL },
14
+ } as const
15
+
16
+ export const OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS = {
17
+ openai: { forceReasoning: true, reasoningEffort: 'high', reasoningSummary: BIFROST_REASONING_SUMMARY_LEVEL },
18
+ } as const
19
+
20
+ export const OPENROUTER_XHIGH_REASONING_PROVIDER_OPTIONS = {
21
+ openai: { forceReasoning: true, reasoningEffort: 'xhigh', reasoningSummary: BIFROST_REASONING_SUMMARY_LEVEL },
22
+ } as const
23
+
24
+ export const OPENROUTER_MEDIUM_REASONING_PROVIDER_OPTIONS = {
25
+ openai: { forceReasoning: true, reasoningEffort: 'medium', reasoningSummary: BIFROST_REASONING_SUMMARY_LEVEL },
26
+ } as const
27
+
28
+ export const OPENROUTER_LOW_REASONING_PROVIDER_OPTIONS = {
29
+ openai: { forceReasoning: true, reasoningEffort: 'low', reasoningSummary: BIFROST_REASONING_SUMMARY_LEVEL },
30
+ } as const
31
+
32
+ export const OPENROUTER_MINIMAL_REASONING_PROVIDER_OPTIONS = {
33
+ openai: { forceReasoning: true, reasoningEffort: 'minimal', reasoningSummary: BIFROST_REASONING_SUMMARY_LEVEL },
34
+ } as const
@@ -0,0 +1 @@
1
+ export const VECTOR_SEARCH_OVERFETCH_MULTIPLIER = 2
package/src/index.ts CHANGED
@@ -2,14 +2,19 @@ export * from './constants/attachments'
2
2
  export * from './constants/workstream'
3
3
  export * from './runtime/agent-types'
4
4
  export * from './runtime/chat-message-metadata'
5
+ export * from './runtime/execution-plan-result'
5
6
  export * from './schemas/chat-api'
6
7
  export * from './schemas/chat-message'
7
8
  export * from './schemas/common'
9
+ export * from './schemas/confidence'
8
10
  export * from './schemas/document'
9
11
  export * from './schemas/error'
10
12
  export * from './schemas/execution-plan'
13
+ export * from './schemas/graph-designer'
11
14
  export * from './schemas/organization'
12
15
  export * from './schemas/organization-api'
16
+ export * from './schemas/playbook'
17
+ export * from './schemas/plugin-coordination'
13
18
  export * from './schemas/recent-activity'
14
19
  export * from './schemas/repository-structure'
15
20
  export * from './schemas/tools'
@@ -17,6 +22,11 @@ export * from './schemas/user'
17
22
  export * from './schemas/user-api'
18
23
  export * from './schemas/workstream'
19
24
  export * from './schemas/workstream-api'
25
+ export * from './constants/model'
26
+ export * from './constants/search'
20
27
  export * from './utils/assistant-text'
28
+ export * from './utils/confidence'
29
+ export * from './utils/date-time'
30
+ export * from './utils/errors'
21
31
  export * from './utils/markdown-normalization'
22
32
  export * from './utils/string'
@@ -9,6 +9,7 @@ export interface CreateRoutedAgentOptions<TTools extends ToolSet = ToolSet> {
9
9
  stopWhen?: StopCondition<TTools> | Array<StopCondition<TTools>>
10
10
  prepareStep?: PrepareStepFunction<TTools>
11
11
  maxRetries?: number
12
+ output?: Output.Output
12
13
  modelOverride?: { model: unknown; providerOptions?: Record<string, unknown> }
13
14
  onFinish?: ToolLoopAgentOnFinishCallback<TTools>
14
15
  }
@@ -14,26 +14,36 @@ export function toTimestamp(value: unknown): number | undefined {
14
14
  return undefined
15
15
  }
16
16
 
17
+ export function requireTimestamp(value: unknown): number {
18
+ const ts = toTimestamp(value)
19
+ if (ts === undefined) throw new Error(`Expected a valid timestamp, got ${String(value)}`)
20
+ return ts
21
+ }
22
+
17
23
  export function getMessageCreatedAt(
18
24
  message: { metadata?: MessageMetadataLike },
19
25
  options?: { fallback?: number },
20
26
  ): number {
21
27
  const createdAt = toTimestamp(message.metadata?.createdAt)
22
28
  if (createdAt !== undefined) return createdAt
23
- return options?.fallback ?? Date.now()
29
+ if (options?.fallback !== undefined) return options.fallback
30
+ throw new Error('Message metadata is missing createdAt timestamp')
24
31
  }
25
32
 
26
33
  export function withCreatedAtMetadata<TMetadata extends MessageMetadataLike | undefined>(
27
34
  metadata: TMetadata,
28
- fallback = Date.now(),
35
+ createdAt?: number,
29
36
  ): NonNullable<TMetadata> & { createdAt: number } {
30
- const next =
31
- metadata && typeof metadata === 'object'
32
- ? ({ ...(metadata as Record<string, unknown>) } as NonNullable<TMetadata>)
33
- : ({} as NonNullable<TMetadata>)
37
+ const next = (
38
+ metadata && typeof metadata === 'object' ? { ...(metadata as Record<string, unknown>) } : {}
39
+ ) as NonNullable<TMetadata>
40
+
41
+ if (typeof createdAt === 'number' && Number.isFinite(createdAt)) {
42
+ next.createdAt = createdAt
43
+ }
34
44
 
35
45
  if (typeof next.createdAt !== 'number' || !Number.isFinite(next.createdAt)) {
36
- next.createdAt = fallback
46
+ throw new Error('withCreatedAtMetadata: createdAt is required but was not provided or present in metadata')
37
47
  }
38
48
 
39
49
  return next as NonNullable<TMetadata> & { createdAt: number }
@@ -41,8 +51,8 @@ export function withCreatedAtMetadata<TMetadata extends MessageMetadataLike | un
41
51
 
42
52
  export function withMessageCreatedAt<TMessage extends { metadata?: MessageMetadataLike }>(
43
53
  message: TMessage,
44
- fallback = Date.now(),
54
+ createdAt?: number,
45
55
  ): TMessage {
46
- const metadata = withCreatedAtMetadata(message.metadata, fallback)
56
+ const metadata = withCreatedAtMetadata(message.metadata, createdAt)
47
57
  return { ...message, metadata }
48
58
  }
@@ -0,0 +1,20 @@
1
+ import type { ExecutionPlanToolResultData } from '../schemas/tools'
2
+
3
+ export function isExecutionPlanResult(value: unknown): value is ExecutionPlanToolResultData {
4
+ return value !== null && value !== undefined && typeof value === 'object' && 'hasPlan' in value
5
+ }
6
+
7
+ export function getLatestExecutionPlanResult(output: unknown): ExecutionPlanToolResultData | null {
8
+ if (isExecutionPlanResult(output)) {
9
+ return output
10
+ }
11
+
12
+ if (Array.isArray(output)) {
13
+ for (let index = output.length - 1; index >= 0; index -= 1) {
14
+ const candidate = getLatestExecutionPlanResult(output[index])
15
+ if (candidate) return candidate
16
+ }
17
+ }
18
+
19
+ return null
20
+ }
@@ -4,6 +4,8 @@ import { WORKSTREAM } from '../constants/workstream'
4
4
 
5
5
  const SURREALDB_RECORD_ID_CLASSES = new Set(['RecordId', 'StringRecordId'])
6
6
 
7
+ export const unixTimestampSchema = z.coerce.date()
8
+
7
9
  function coerceRecordIdToString(val: unknown): unknown {
8
10
  if (val === null || val === undefined) return val
9
11
  if (typeof val === 'string') return val
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod'
2
+
3
+ export const ConfidenceDimensionSchema = z.enum([
4
+ 'data-quality',
5
+ 'source-reliability',
6
+ 'temporal-relevance',
7
+ 'consensus',
8
+ 'completeness',
9
+ ])
10
+ export type ConfidenceDimension = z.infer<typeof ConfidenceDimensionSchema>
11
+
12
+ export const ConfidenceMethodSchema = z.enum(['weighted-average', 'min', 'bayesian'])
13
+ export type ConfidenceMethod = z.infer<typeof ConfidenceMethodSchema>
14
+
15
+ export const ConfidenceScoreSchema = z.object({
16
+ overall: z.number().min(0).max(1),
17
+ dimensions: z.record(z.string(), z.number().min(0).max(1)).default({}),
18
+ method: ConfidenceMethodSchema.default('weighted-average'),
19
+ })
20
+ export type ConfidenceScore = z.infer<typeof ConfidenceScoreSchema>
@@ -2,7 +2,11 @@ import { z } from 'zod'
2
2
 
3
3
  import { recordIdSchema } from './common'
4
4
 
5
- const unixTimestampSchema = z.coerce.date()
5
+ /** For DB record schemas — accepts Date objects from SurrealDB and coerces strings */
6
+ const dbDateTimeSchema = z.coerce.date()
7
+
8
+ /** For tool/API schemas that need JSON Schema representation — accepts ISO strings only */
9
+ const apiDateTimeSchema = z.string().datetime({ offset: true })
6
10
 
7
11
  const planSchemaLiteralSchema = z.union([z.string(), z.number(), z.boolean(), z.null()])
8
12
 
@@ -51,17 +55,28 @@ export const PlanNodeTypeSchema = z
51
55
  'switch',
52
56
  'join',
53
57
  'subgraph',
58
+ 'monitoring',
59
+ 'deliberation-fork',
54
60
  ])
55
61
  .meta({ id: 'PlanNodeTypeSchema' })
56
62
  export type PlanNodeType = z.infer<typeof PlanNodeTypeSchema>
57
63
 
58
64
  export const PlanNodeExecutorTypeSchema = z
59
- .enum(['agent', 'plugin', 'user', 'system'])
65
+ .enum(['agent', 'plugin', 'user', 'system', 'skill'])
60
66
  .meta({ id: 'PlanNodeExecutorTypeSchema' })
61
67
  export type PlanNodeExecutorType = z.infer<typeof PlanNodeExecutorTypeSchema>
62
68
 
63
69
  export const PlanArtifactKindSchema = z
64
- .enum(['json', 'markdown', 'file', 'external-ref', 'record'])
70
+ .enum([
71
+ 'json',
72
+ 'markdown',
73
+ 'file',
74
+ 'external-ref',
75
+ 'record',
76
+ 'time-series',
77
+ 'deliberation-evidence',
78
+ 'recommendation',
79
+ ])
65
80
  .meta({ id: 'PlanArtifactKindSchema' })
66
81
  export type PlanArtifactKind = z.infer<typeof PlanArtifactKindSchema>
67
82
 
@@ -97,12 +112,24 @@ export const PlanSpecStatusSchema = z.enum(['compiled', 'superseded']).meta({ id
97
112
  export type PlanSpecStatus = z.infer<typeof PlanSpecStatusSchema>
98
113
 
99
114
  export const PlanRunStatusSchema = z
100
- .enum(['running', 'awaiting-human', 'blocked', 'completed', 'failed', 'aborted'])
115
+ .enum(['running', 'awaiting-human', 'blocked', 'completed', 'failed', 'aborted', 'scheduled'])
101
116
  .meta({ id: 'PlanRunStatusSchema' })
102
117
  export type PlanRunStatus = z.infer<typeof PlanRunStatusSchema>
103
118
 
104
119
  export const PlanNodeRunStatusSchema = z
105
- .enum(['pending', 'ready', 'running', 'awaiting-human', 'completed', 'partial', 'blocked', 'failed', 'skipped'])
120
+ .enum([
121
+ 'pending',
122
+ 'ready',
123
+ 'running',
124
+ 'awaiting-human',
125
+ 'completed',
126
+ 'partial',
127
+ 'blocked',
128
+ 'failed',
129
+ 'skipped',
130
+ 'scheduled',
131
+ 'monitoring',
132
+ ])
106
133
  .meta({ id: 'PlanNodeRunStatusSchema' })
107
134
  export type PlanNodeRunStatus = z.infer<typeof PlanNodeRunStatusSchema>
108
135
 
@@ -140,13 +167,49 @@ export const PlanEventTypeSchema = z
140
167
  'checkpoint-saved',
141
168
  'run-resumed',
142
169
  'validation-reported',
170
+ 'schedule-created',
171
+ 'schedule-fired',
172
+ 'schedule-missed',
173
+ 'deadline-warning',
174
+ 'deadline-missed',
175
+ 'node-scheduled',
176
+ 'node-monitoring',
177
+ 'cycle-started',
178
+ 'cycle-completed',
179
+ 'feedback-analyzed',
143
180
  ])
144
181
  .meta({ id: 'PlanEventTypeSchema' })
145
182
  export type PlanEventType = z.infer<typeof PlanEventTypeSchema>
146
183
 
147
- export const PlanNodeOwnerSchema = z
148
- .object({ executorType: PlanNodeExecutorTypeSchema, ref: z.string().trim().min(1).max(200) })
184
+ const planOwnerRefSchema = z.string().trim().min(1).max(200)
185
+ const planOwnerOperationSchema = z.string().trim().min(1).max(200)
186
+
187
+ export const AgentPlanNodeOwnerSchema = z.object({ executorType: z.literal('agent'), ref: planOwnerRefSchema }).strict()
188
+ export type AgentPlanNodeOwner = z.infer<typeof AgentPlanNodeOwnerSchema>
189
+
190
+ export const PluginPlanNodeOwnerSchema = z
191
+ .object({ executorType: z.literal('plugin'), ref: planOwnerRefSchema, operation: planOwnerOperationSchema })
149
192
  .strict()
193
+ export type PluginPlanNodeOwner = z.infer<typeof PluginPlanNodeOwnerSchema>
194
+
195
+ export const UserPlanNodeOwnerSchema = z.object({ executorType: z.literal('user'), ref: planOwnerRefSchema }).strict()
196
+ export type UserPlanNodeOwner = z.infer<typeof UserPlanNodeOwnerSchema>
197
+
198
+ export const SystemPlanNodeOwnerSchema = z
199
+ .object({ executorType: z.literal('system'), ref: planOwnerRefSchema, operation: planOwnerOperationSchema })
200
+ .strict()
201
+ export type SystemPlanNodeOwner = z.infer<typeof SystemPlanNodeOwnerSchema>
202
+
203
+ export const SkillPlanNodeOwnerSchema = z.object({ executorType: z.literal('skill'), ref: planOwnerRefSchema }).strict()
204
+ export type SkillPlanNodeOwner = z.infer<typeof SkillPlanNodeOwnerSchema>
205
+
206
+ export const PlanNodeOwnerSchema = z.discriminatedUnion('executorType', [
207
+ AgentPlanNodeOwnerSchema,
208
+ PluginPlanNodeOwnerSchema,
209
+ UserPlanNodeOwnerSchema,
210
+ SystemPlanNodeOwnerSchema,
211
+ SkillPlanNodeOwnerSchema,
212
+ ])
150
213
  export type PlanNodeOwner = z.infer<typeof PlanNodeOwnerSchema>
151
214
 
152
215
  export const PlanArtifactSpecSchema = z
@@ -197,7 +260,241 @@ export const PlanContextPolicySchema = z
197
260
  .strict()
198
261
  export type PlanContextPolicy = z.infer<typeof PlanContextPolicySchema>
199
262
 
200
- const planStructuredPayloadSchema = z.union([z.record(z.string(), z.unknown()), z.array(z.unknown())])
263
+ export const ScheduleTypeSchema = z.enum(['immediate', 'absolute', 'relative', 'cron', 'monitoring'])
264
+ export type ScheduleType = z.infer<typeof ScheduleTypeSchema>
265
+
266
+ export const MissedSchedulePolicySchema = z.enum(['skip', 'run-immediately', 'run-next-window'])
267
+ export type MissedSchedulePolicy = z.infer<typeof MissedSchedulePolicySchema>
268
+
269
+ export const PlanScheduleSpecSchema = z
270
+ .object({
271
+ type: ScheduleTypeSchema,
272
+ at: apiDateTimeSchema.optional(),
273
+ delayMs: z.number().int().positive().optional(),
274
+ cron: z.string().trim().min(1).max(200).optional(),
275
+ intervalMs: z.number().int().positive().optional(),
276
+ maxFires: z.number().int().positive().optional(),
277
+ missedPolicy: MissedSchedulePolicySchema.default('run-immediately'),
278
+ })
279
+ .strict()
280
+ export type PlanScheduleSpec = z.infer<typeof PlanScheduleSpecSchema>
281
+
282
+ export const DeadlineActionSchema = z.enum(['notify', 'escalate', 'block', 'fail'])
283
+ export type DeadlineAction = z.infer<typeof DeadlineActionSchema>
284
+
285
+ export const DeadlineReminderSchema = z
286
+ .object({
287
+ beforeMs: z.number().int().positive(),
288
+ action: DeadlineActionSchema.default('notify'),
289
+ message: z.string().trim().min(1).max(500).optional(),
290
+ })
291
+ .strict()
292
+ export type DeadlineReminder = z.infer<typeof DeadlineReminderSchema>
293
+
294
+ export const DeadlineSpecSchema = z
295
+ .object({
296
+ dueAt: apiDateTimeSchema.optional(),
297
+ durationMs: z.number().int().positive().optional(),
298
+ reminders: z.array(DeadlineReminderSchema).default([]),
299
+ missAction: DeadlineActionSchema.default('fail'),
300
+ })
301
+ .strict()
302
+ export type DeadlineSpec = z.infer<typeof DeadlineSpecSchema>
303
+
304
+ export const NotificationSeveritySchema = z.enum(['info', 'warning', 'urgent', 'critical'])
305
+ export type NotificationSeverity = z.infer<typeof NotificationSeveritySchema>
306
+
307
+ export const PlanScheduleStatusSchema = z.enum(['active', 'paused', 'completed', 'cancelled'])
308
+ export type PlanScheduleStatus = z.infer<typeof PlanScheduleStatusSchema>
309
+
310
+ export const PlanScheduleRecordSchema = z.object({
311
+ id: recordIdSchema,
312
+ organizationId: recordIdSchema,
313
+ workstreamId: recordIdSchema,
314
+ planSpecId: recordIdSchema.optional(),
315
+ runId: recordIdSchema.optional(),
316
+ nodeId: z.string().optional(),
317
+ scheduleSpec: PlanScheduleSpecSchema,
318
+ status: PlanScheduleStatusSchema,
319
+ fireCount: z.number().int().nonnegative().default(0),
320
+ nextFireAt: dbDateTimeSchema.optional(),
321
+ lastFiredAt: dbDateTimeSchema.optional(),
322
+ createdAt: dbDateTimeSchema,
323
+ updatedAt: dbDateTimeSchema.optional(),
324
+ })
325
+ export type PlanScheduleRecord = z.infer<typeof PlanScheduleRecordSchema>
326
+
327
+ export const PlanTemplateSourceSchema = z.enum(['user', 'playbook', 'system']).default('user')
328
+ export type PlanTemplateSource = z.infer<typeof PlanTemplateSourceSchema>
329
+
330
+ export const CycleFrequencySchema = z.enum(['daily', 'weekly', 'biweekly', 'monthly', 'quarterly', 'custom'])
331
+ export type CycleFrequency = z.infer<typeof CycleFrequencySchema>
332
+
333
+ export const CarryForwardPolicySchema = z.enum(['none', 'incomplete-only', 'all-pending'])
334
+ export type CarryForwardPolicy = z.infer<typeof CarryForwardPolicySchema>
335
+
336
+ export const CycleScheduleSchema = z
337
+ .object({
338
+ frequency: CycleFrequencySchema,
339
+ customIntervalMs: z.number().int().positive().optional(),
340
+ startAt: apiDateTimeSchema,
341
+ endAt: apiDateTimeSchema.optional(),
342
+ })
343
+ .strict()
344
+ export type CycleSchedule = z.infer<typeof CycleScheduleSchema>
345
+
346
+ export const PlanCycleStatusSchema = z.enum(['active', 'paused', 'completed', 'cancelled'])
347
+ export type PlanCycleStatus = z.infer<typeof PlanCycleStatusSchema>
348
+
349
+ export const ExecutionModeSchema = z.enum(['linear', 'graph-lite', 'graph-full']).default('linear')
350
+ export type ExecutionMode = z.infer<typeof ExecutionModeSchema>
351
+
352
+ export const WriteIntentActionSchema = z.enum(['create', 'append', 'update'])
353
+ export type WriteIntentAction = z.infer<typeof WriteIntentActionSchema>
354
+
355
+ export const WriteIntentSchema = z
356
+ .object({
357
+ targetPath: z.string().trim().min(1).max(500),
358
+ action: WriteIntentActionSchema,
359
+ payload: z.union([z.record(z.string(), z.unknown()), z.array(z.unknown()), z.string()]),
360
+ })
361
+ .strict()
362
+ export type WriteIntent = z.infer<typeof WriteIntentSchema>
363
+
364
+ export const WriteValidationErrorSchema = z
365
+ .object({
366
+ targetPath: z.string(),
367
+ action: WriteIntentActionSchema,
368
+ status: z.enum(['pass', 'fail']),
369
+ issues: z.array(
370
+ z.object({
371
+ code: z.string(),
372
+ message: z.string(),
373
+ path: z.string().optional(),
374
+ suggestion: z.string().optional(),
375
+ }),
376
+ ),
377
+ })
378
+ .strict()
379
+ export type WriteValidationError = z.infer<typeof WriteValidationErrorSchema>
380
+
381
+ export const NodeWorkspaceEntrySchema = z
382
+ .object({
383
+ targetPath: z.string(),
384
+ action: WriteIntentActionSchema,
385
+ payload: z.unknown(),
386
+ validatedAt: apiDateTimeSchema,
387
+ })
388
+ .strict()
389
+ export type NodeWorkspaceEntry = z.infer<typeof NodeWorkspaceEntrySchema>
390
+
391
+ export const NodeResultQualitySchema = z.enum(['full', 'partial']).default('full')
392
+ export type NodeResultQuality = z.infer<typeof NodeResultQualitySchema>
393
+
394
+ const planJsonValueSchema: z.ZodType<unknown> = z.lazy(() =>
395
+ z.union([z.string(), z.number(), z.boolean(), z.null(), z.array(planJsonValueSchema), planStructuredObjectSchema]),
396
+ )
397
+ const planStructuredObjectSchema: z.ZodType<Record<string, unknown>> = z.lazy(() =>
398
+ z.object({}).catchall(planJsonValueSchema),
399
+ )
400
+ const planStructuredPayloadSchema: z.ZodType<Record<string, unknown> | unknown[]> = z.union([
401
+ planStructuredObjectSchema,
402
+ z.array(planJsonValueSchema),
403
+ ])
404
+ export type PlanStructuredPayload = z.infer<typeof planStructuredPayloadSchema>
405
+
406
+ export const PlanArtifactSubmissionSchema = z
407
+ .object({
408
+ name: z.string().trim().min(1).max(200),
409
+ kind: PlanArtifactKindSchema,
410
+ pointer: z.string().trim().min(1).max(500),
411
+ schemaRef: z.string().trim().min(1).max(200).optional(),
412
+ description: z.string().trim().min(1).max(1000).optional(),
413
+ payload: planStructuredPayloadSchema.optional(),
414
+ })
415
+ .strict()
416
+ export type PlanArtifactSubmission = z.infer<typeof PlanArtifactSubmissionSchema>
417
+
418
+ export const PlanNodeResultSubmissionSchema = z
419
+ .object({
420
+ structuredOutput: planStructuredObjectSchema.optional(),
421
+ artifacts: z.array(PlanArtifactSubmissionSchema).default([]),
422
+ notes: z.string().trim().min(1).max(2000).optional(),
423
+ quality: NodeResultQualitySchema.optional(),
424
+ })
425
+ .strict()
426
+ export type PlanNodeResultSubmission = z.infer<typeof PlanNodeResultSubmissionSchema>
427
+ export type PlanNodeResult = PlanNodeResultSubmission
428
+
429
+ export interface OwnershipDispatchContext {
430
+ organizationId: string
431
+ workstreamId: string
432
+ planId: string
433
+ nodeId: string
434
+ leadAgentId: string
435
+ userId?: string
436
+ userName?: string
437
+ }
438
+
439
+ export const MonitoringWindowConfigSchema = z.object({
440
+ durationMs: z.number().int().positive(),
441
+ initialIntervalMs: z.number().int().positive(),
442
+ decayFactor: z.number().min(0.1).max(1.0).default(0.8),
443
+ maxIntervalMs: z.number().int().positive(),
444
+ earlyTermination: z
445
+ .object({ condition: z.string().trim().min(1).max(500), minSamples: z.number().int().positive().default(3) })
446
+ .optional(),
447
+ })
448
+ export type MonitoringWindowConfig = z.infer<typeof MonitoringWindowConfigSchema>
449
+
450
+ export const PlanDependencyTriggerModeSchema = z.enum(['block', 'notify', 'best-effort'])
451
+ export type PlanDependencyTriggerMode = z.infer<typeof PlanDependencyTriggerModeSchema>
452
+
453
+ export const PlanDependencySchema = z.object({
454
+ sourcePlanTitle: z.string().trim().min(1).max(200),
455
+ sourceNodeId: z.string().trim().min(1).max(200),
456
+ artifactName: z.string().trim().min(1).max(200),
457
+ triggerMode: PlanDependencyTriggerModeSchema.default('block'),
458
+ maxStalenessMs: z.number().int().positive().optional(),
459
+ })
460
+ export type PlanDependency = z.infer<typeof PlanDependencySchema>
461
+
462
+ export const DeliberationBranchSchema = z.object({
463
+ branchId: z.string().trim().min(1).max(200),
464
+ label: z.string().trim().min(1).max(300),
465
+ entryNodeId: z.string().trim().min(1).max(200),
466
+ })
467
+ export type DeliberationBranch = z.infer<typeof DeliberationBranchSchema>
468
+
469
+ export const DeliberationForkConfigSchema = z.object({
470
+ branches: z.array(DeliberationBranchSchema).min(2).max(8),
471
+ resolutionGateNodeId: z.string().trim().min(1).max(200),
472
+ })
473
+ export type DeliberationForkConfig = z.infer<typeof DeliberationForkConfigSchema>
474
+
475
+ export const ProvenanceNodeSchema = z.object({
476
+ nodeId: z.string(),
477
+ label: z.string(),
478
+ artifacts: z.array(z.object({ name: z.string(), kind: PlanArtifactKindSchema, id: z.string() })),
479
+ })
480
+ export type ProvenanceNode = z.infer<typeof ProvenanceNodeSchema>
481
+
482
+ export const ProvenanceChainSchema = z.object({
483
+ root: z.object({ nodeId: z.string() }),
484
+ chain: z.array(ProvenanceNodeSchema),
485
+ depth: z.number().int().nonnegative(),
486
+ })
487
+ export type ProvenanceChain = z.infer<typeof ProvenanceChainSchema>
488
+
489
+ export const ImpactAnalysisSchema = z.object({
490
+ sourceNodeId: z.string(),
491
+ affectedNodes: z.array(z.object({ nodeId: z.string(), label: z.string(), status: PlanNodeRunStatusSchema })),
492
+ affectedArtifacts: z.array(z.object({ name: z.string(), nodeId: z.string() })),
493
+ })
494
+ export type ImpactAnalysis = z.infer<typeof ImpactAnalysisSchema>
495
+
496
+ export const ConvergenceStateSchema = z.enum(['progressing', 'stalled', 'diverging', 'converging'])
497
+ export type ConvergenceState = z.infer<typeof ConvergenceStateSchema>
201
498
 
202
499
  export const PlanNodeSpecSchema = z
203
500
  .object({
@@ -221,6 +518,11 @@ export const PlanNodeSpecSchema = z
221
518
  attachmentPolicy: 'referenced-only',
222
519
  webPolicy: 'allowed',
223
520
  }),
521
+ schedule: PlanScheduleSpecSchema.optional(),
522
+ deadline: DeadlineSpecSchema.optional(),
523
+ monitoringConfig: MonitoringWindowConfigSchema.optional(),
524
+ delayAfterPredecessorMs: z.number().int().positive().optional(),
525
+ deliberationConfig: DeliberationForkConfigSchema.optional(),
224
526
  })
225
527
  .strict()
226
528
  export type PlanNodeSpec = z.infer<typeof PlanNodeSpecSchema>
@@ -244,10 +546,16 @@ export const PlanDraftSchema = z
244
546
  nodes: z.array(PlanNodeSpecSchema).min(1).max(32),
245
547
  edges: z.array(PlanEdgeSpecSchema).default([]),
246
548
  entryNodeIds: z.array(z.string().trim().min(1).max(200)).min(1).optional(),
549
+ executionMode: ExecutionModeSchema.optional(),
550
+ schedule: PlanScheduleSpecSchema.optional(),
551
+ dependencies: z.array(PlanDependencySchema).optional(),
247
552
  })
248
553
  .strict()
249
554
  export type PlanDraft = z.infer<typeof PlanDraftSchema>
250
555
 
556
+ export const ContextEnrichmentEntrySchema = z.object({ type: z.string(), content: z.string() })
557
+ export type ContextEnrichmentEntry = z.infer<typeof ContextEnrichmentEntrySchema>
558
+
251
559
  export const PlanSpecSchema = z.object({
252
560
  id: recordIdSchema,
253
561
  organizationId: recordIdSchema,
@@ -260,10 +568,14 @@ export const PlanSpecSchema = z.object({
260
568
  schemaRegistry: PlanSchemaRegistrySchema,
261
569
  edges: z.array(PlanEdgeSpecSchema),
262
570
  entryNodeIds: z.array(z.string()),
571
+ executionMode: ExecutionModeSchema,
572
+ schedule: PlanScheduleSpecSchema.optional(),
573
+ dependencies: z.array(PlanDependencySchema).optional(),
574
+ contextEnrichments: z.array(ContextEnrichmentEntrySchema).optional(),
263
575
  replacedSpecId: recordIdSchema.optional(),
264
- createdAt: unixTimestampSchema,
265
- updatedAt: unixTimestampSchema.optional(),
266
- compiledAt: unixTimestampSchema.optional(),
576
+ createdAt: dbDateTimeSchema,
577
+ updatedAt: dbDateTimeSchema.optional(),
578
+ compiledAt: dbDateTimeSchema.optional(),
267
579
  })
268
580
  export type PlanSpecRecord = z.infer<typeof PlanSpecSchema>
269
581
 
@@ -287,10 +599,15 @@ export const PlanNodeSpecRecordSchema = z.object({
287
599
  timeoutMs: z.number().int().positive().optional(),
288
600
  toolPolicy: PlanToolPolicySchema,
289
601
  contextPolicy: PlanContextPolicySchema,
602
+ schedule: PlanScheduleSpecSchema.optional(),
603
+ deadline: DeadlineSpecSchema.optional(),
604
+ monitoringConfig: MonitoringWindowConfigSchema.optional(),
605
+ delayAfterPredecessorMs: z.number().int().positive().optional(),
606
+ deliberationConfig: DeliberationForkConfigSchema.optional(),
290
607
  upstreamNodeIds: z.array(z.string()).default([]),
291
608
  downstreamNodeIds: z.array(z.string()).default([]),
292
- createdAt: unixTimestampSchema,
293
- updatedAt: unixTimestampSchema.optional(),
609
+ createdAt: dbDateTimeSchema,
610
+ updatedAt: dbDateTimeSchema.optional(),
294
611
  })
295
612
  export type PlanNodeSpecRecord = z.infer<typeof PlanNodeSpecRecordSchema>
296
613
 
@@ -307,10 +624,12 @@ export const PlanRunSchema = z.object({
307
624
  failureCount: z.number().int().nonnegative(),
308
625
  replacedRunId: recordIdSchema.optional(),
309
626
  lastCheckpointId: recordIdSchema.optional(),
310
- createdAt: unixTimestampSchema,
311
- updatedAt: unixTimestampSchema.optional(),
312
- startedAt: unixTimestampSchema.optional(),
313
- completedAt: unixTimestampSchema.optional(),
627
+ scheduledAt: dbDateTimeSchema.optional(),
628
+ scheduleId: recordIdSchema.optional(),
629
+ createdAt: dbDateTimeSchema,
630
+ updatedAt: dbDateTimeSchema.optional(),
631
+ startedAt: dbDateTimeSchema.optional(),
632
+ completedAt: dbDateTimeSchema.optional(),
314
633
  })
315
634
  export type PlanRunRecord = z.infer<typeof PlanRunSchema>
316
635
 
@@ -328,11 +647,12 @@ export const PlanNodeRunSchema = z.object({
328
647
  latestAttemptId: recordIdSchema.optional(),
329
648
  blockedReason: z.string().optional(),
330
649
  failureClass: PlanFailureClassSchema.optional(),
331
- readyAt: unixTimestampSchema.optional(),
332
- startedAt: unixTimestampSchema.optional(),
333
- completedAt: unixTimestampSchema.optional(),
334
- createdAt: unixTimestampSchema,
335
- updatedAt: unixTimestampSchema.optional(),
650
+ scheduledAt: dbDateTimeSchema.optional(),
651
+ readyAt: dbDateTimeSchema.optional(),
652
+ startedAt: dbDateTimeSchema.optional(),
653
+ completedAt: dbDateTimeSchema.optional(),
654
+ createdAt: dbDateTimeSchema,
655
+ updatedAt: dbDateTimeSchema.optional(),
336
656
  })
337
657
  export type PlanNodeRunRecord = z.infer<typeof PlanNodeRunSchema>
338
658
 
@@ -343,11 +663,11 @@ export const PlanNodeAttemptSchema = z.object({
343
663
  nodeId: z.string(),
344
664
  emittedBy: z.string(),
345
665
  status: PlanAttemptStatusSchema,
346
- structuredOutput: z.record(z.string(), z.unknown()).optional(),
666
+ structuredOutput: planStructuredObjectSchema.optional(),
347
667
  notes: z.string().optional(),
348
668
  validationIssueIds: z.array(recordIdSchema).default([]),
349
669
  failureClass: PlanFailureClassSchema.optional(),
350
- createdAt: unixTimestampSchema,
670
+ createdAt: dbDateTimeSchema,
351
671
  })
352
672
  export type PlanNodeAttemptRecord = z.infer<typeof PlanNodeAttemptSchema>
353
673
 
@@ -362,7 +682,7 @@ export const PlanArtifactSchema = z.object({
362
682
  schemaRef: z.string().optional(),
363
683
  description: z.string().optional(),
364
684
  payload: planStructuredPayloadSchema.optional(),
365
- createdAt: unixTimestampSchema,
685
+ createdAt: dbDateTimeSchema,
366
686
  })
367
687
  export type PlanArtifactRecord = z.infer<typeof PlanArtifactSchema>
368
688
 
@@ -376,7 +696,7 @@ export const PlanValidationIssueSchema = z.object({
376
696
  code: z.string(),
377
697
  message: z.string(),
378
698
  detail: z.record(z.string(), z.unknown()).optional(),
379
- createdAt: unixTimestampSchema,
699
+ createdAt: dbDateTimeSchema,
380
700
  })
381
701
  export type PlanValidationIssueRecord = z.infer<typeof PlanValidationIssueSchema>
382
702
 
@@ -390,7 +710,7 @@ export const PlanCheckpointSchema = z.object({
390
710
  artifactIds: z.array(recordIdSchema).default([]),
391
711
  lastCompletedNodeIds: z.array(z.string()).default([]),
392
712
  snapshot: z.record(z.string(), z.unknown()),
393
- createdAt: unixTimestampSchema,
713
+ createdAt: dbDateTimeSchema,
394
714
  })
395
715
  export type PlanCheckpointRecord = z.infer<typeof PlanCheckpointSchema>
396
716
 
@@ -407,9 +727,9 @@ export const PlanApprovalSchema = z.object({
407
727
  approvalMessageId: z.string().optional(),
408
728
  comments: z.string().optional(),
409
729
  requiredEdits: z.array(z.string()).default([]),
410
- createdAt: unixTimestampSchema,
411
- updatedAt: unixTimestampSchema.optional(),
412
- respondedAt: unixTimestampSchema.optional(),
730
+ createdAt: dbDateTimeSchema,
731
+ updatedAt: dbDateTimeSchema.optional(),
732
+ respondedAt: dbDateTimeSchema.optional(),
413
733
  })
414
734
  export type PlanApprovalRecord = z.infer<typeof PlanApprovalSchema>
415
735
 
@@ -426,7 +746,7 @@ export const PlanEventSchema = z.object({
426
746
  message: z.string(),
427
747
  detail: z.record(z.string(), z.unknown()).optional(),
428
748
  emittedBy: z.string(),
429
- createdAt: unixTimestampSchema,
749
+ createdAt: dbDateTimeSchema,
430
750
  })
431
751
  export type PlanEventRecord = z.infer<typeof PlanEventSchema>
432
752
 
@@ -447,6 +767,11 @@ export const SerializablePlanNodeSchema = z.object({
447
767
  timeoutMs: z.number().int().positive().nullish(),
448
768
  toolPolicy: PlanToolPolicySchema,
449
769
  contextPolicy: PlanContextPolicySchema,
770
+ schedule: PlanScheduleSpecSchema.nullish(),
771
+ deadline: DeadlineSpecSchema.nullish(),
772
+ monitoringConfig: MonitoringWindowConfigSchema.nullish(),
773
+ delayAfterPredecessorMs: z.number().int().positive().nullish(),
774
+ deliberationConfig: DeliberationForkConfigSchema.nullish(),
450
775
  status: PlanNodeRunStatusSchema,
451
776
  attemptCount: z.number().int().nonnegative(),
452
777
  retryCount: z.number().int().nonnegative(),
@@ -544,6 +869,8 @@ export const SerializableExecutionPlanProgressSchema = z.object({
544
869
  blocked: z.number().int().nonnegative(),
545
870
  failed: z.number().int().nonnegative(),
546
871
  skipped: z.number().int().nonnegative(),
872
+ scheduled: z.number().int().nonnegative(),
873
+ monitoring: z.number().int().nonnegative(),
547
874
  completionRatio: z.number().min(0).max(1).nullish(),
548
875
  })
549
876
  export type SerializableExecutionPlanProgress = z.infer<typeof SerializableExecutionPlanProgressSchema>
@@ -558,9 +885,11 @@ export const SerializableExecutionPlanSchema = z.object({
558
885
  version: z.number().int().positive(),
559
886
  status: PlanRunStatusSchema,
560
887
  leadAgentId: z.string(),
888
+ executionMode: ExecutionModeSchema,
561
889
  schemaRegistry: PlanSchemaRegistrySchema,
562
890
  entryNodeIds: z.array(z.string()),
563
891
  edges: z.array(PlanEdgeSpecSchema),
892
+ schedule: PlanScheduleSpecSchema.nullish(),
564
893
  activeNodeIds: z.array(z.string()),
565
894
  readyNodeIds: z.array(z.string()),
566
895
  waitingNodeId: z.string().nullish(),
@@ -578,3 +907,97 @@ export const SerializableExecutionPlanSchema = z.object({
578
907
  recentEvents: z.array(SerializablePlanEventSchema),
579
908
  })
580
909
  export type SerializableExecutionPlan = z.infer<typeof SerializableExecutionPlanSchema>
910
+
911
+ export const PlanTemplateRecordSchema = z.object({
912
+ id: recordIdSchema,
913
+ organizationId: recordIdSchema,
914
+ name: z.string(),
915
+ description: z.string().optional(),
916
+ draft: PlanDraftSchema,
917
+ tags: z.array(z.string()).default([]),
918
+ source: PlanTemplateSourceSchema,
919
+ sourceRef: z.string().optional(),
920
+ createdAt: dbDateTimeSchema,
921
+ updatedAt: dbDateTimeSchema.optional(),
922
+ })
923
+ export type PlanTemplateRecord = z.infer<typeof PlanTemplateRecordSchema>
924
+
925
+ export const PlanCycleRecordSchema = z.object({
926
+ id: recordIdSchema,
927
+ organizationId: recordIdSchema,
928
+ workstreamId: recordIdSchema,
929
+ templateId: recordIdSchema,
930
+ name: z.string(),
931
+ schedule: CycleScheduleSchema,
932
+ carryForwardPolicy: CarryForwardPolicySchema.default('incomplete-only'),
933
+ status: PlanCycleStatusSchema,
934
+ currentIteration: z.number().int().nonnegative().default(0),
935
+ currentRunId: recordIdSchema.optional(),
936
+ scheduleId: recordIdSchema.optional(),
937
+ createdAt: dbDateTimeSchema,
938
+ updatedAt: dbDateTimeSchema.optional(),
939
+ })
940
+ export type PlanCycleRecord = z.infer<typeof PlanCycleRecordSchema>
941
+
942
+ export const ContextEnrichmentSchema = z.object({
943
+ domain: z.string().trim().min(1).max(200),
944
+ data: z.record(z.string(), z.unknown()),
945
+ confidence: z.number().min(0).max(1),
946
+ })
947
+ export type ContextEnrichment = z.infer<typeof ContextEnrichmentSchema>
948
+
949
+ export const EvidenceRecordSchema = z.object({
950
+ sourceType: z.enum(['artifact', 'metric', 'pattern', 'external']),
951
+ sourceId: z.string().trim().min(1).max(200),
952
+ summary: z.string().trim().min(1).max(1000),
953
+ confidence: z.number().min(0).max(1),
954
+ })
955
+ export type EvidenceRecord = z.infer<typeof EvidenceRecordSchema>
956
+
957
+ export const RecommendationTypeSchema = z.enum(['optimization', 'warning', 'pattern'])
958
+ export type RecommendationType = z.infer<typeof RecommendationTypeSchema>
959
+
960
+ export const RecommendationTargetSchema = z.enum(['node', 'edge', 'plan', 'playbook'])
961
+ export type RecommendationTarget = z.infer<typeof RecommendationTargetSchema>
962
+
963
+ export const RecommendationSchema = z.object({
964
+ type: RecommendationTypeSchema,
965
+ target: RecommendationTargetSchema,
966
+ targetId: z.string().optional(),
967
+ description: z.string().trim().min(1).max(2000),
968
+ evidence: z.array(EvidenceRecordSchema),
969
+ confidence: z.number().min(0).max(1),
970
+ })
971
+ export type Recommendation = z.infer<typeof RecommendationSchema>
972
+
973
+ export const NodeQualityMetricsSchema = z.object({
974
+ executionTimeMs: z.number().int().nonnegative(),
975
+ attemptCount: z.number().int().nonnegative(),
976
+ artifactCount: z.number().int().nonnegative(),
977
+ validationIssueCount: z.number().int().nonnegative(),
978
+ ownerRef: z.string(),
979
+ ownerType: PlanNodeExecutorTypeSchema,
980
+ nodeType: PlanNodeTypeSchema,
981
+ })
982
+ export type NodeQualityMetrics = z.infer<typeof NodeQualityMetricsSchema>
983
+
984
+ export const InstitutionalMemoryTypeSchema = z.enum([
985
+ 'execution-pattern',
986
+ 'failure-pattern',
987
+ 'agent-affinity',
988
+ 'timing-pattern',
989
+ 'quality-pattern',
990
+ ])
991
+ export type InstitutionalMemoryType = z.infer<typeof InstitutionalMemoryTypeSchema>
992
+
993
+ export const InstitutionalMemorySchema = z.object({
994
+ id: recordIdSchema,
995
+ organizationId: recordIdSchema,
996
+ type: InstitutionalMemoryTypeSchema,
997
+ pattern: z.record(z.string(), z.unknown()),
998
+ confidence: z.number().min(0).max(1),
999
+ sampleCount: z.number().int().positive(),
1000
+ createdAt: dbDateTimeSchema,
1001
+ updatedAt: dbDateTimeSchema.optional(),
1002
+ })
1003
+ export type InstitutionalMemory = z.infer<typeof InstitutionalMemorySchema>
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod'
2
+
3
+ import { PlanArtifactKindSchema, PlanDraftSchema } from './execution-plan'
4
+
5
+ export const GraphDesignRequestSchema = z.object({
6
+ objective: z.string().trim().min(1).max(4000),
7
+ constraints: z.array(z.string().trim().min(1).max(1000)).default([]),
8
+ availableAgents: z.array(z.object({ agentId: z.string(), capabilities: z.array(z.string()) })),
9
+ availablePlugins: z.array(z.object({ pluginRef: z.string(), operations: z.array(z.string()) })),
10
+ contextArtifacts: z
11
+ .array(z.object({ name: z.string(), kind: PlanArtifactKindSchema, summary: z.string().optional() }))
12
+ .default([]),
13
+ })
14
+ export type GraphDesignRequest = z.infer<typeof GraphDesignRequestSchema>
15
+
16
+ export const GraphDesignResponseSchema = z.object({
17
+ draft: PlanDraftSchema,
18
+ reasoning: z.string().trim().min(1).max(4000),
19
+ confidence: z.number().min(0).max(1),
20
+ })
21
+ export type GraphDesignResponse = z.infer<typeof GraphDesignResponseSchema>
@@ -0,0 +1,33 @@
1
+ import { z } from 'zod'
2
+
3
+ import { recordIdSchema } from './common'
4
+
5
+ const unixTimestampSchema = z.coerce.date()
6
+
7
+ export const PlaybookVersionStatusSchema = z.enum(['active', 'testing', 'rolled-back', 'archived'])
8
+ export type PlaybookVersionStatus = z.infer<typeof PlaybookVersionStatusSchema>
9
+
10
+ export const PlaybookVersionSchema = z.object({
11
+ id: recordIdSchema,
12
+ playbookId: recordIdSchema,
13
+ version: z.number().int().positive(),
14
+ parentVersionId: recordIdSchema.optional(),
15
+ appliedRecommendations: z.array(z.string()).default([]),
16
+ qualityScore: z.number().min(0).max(1).optional(),
17
+ status: PlaybookVersionStatusSchema,
18
+ createdAt: unixTimestampSchema,
19
+ })
20
+ export type PlaybookVersion = z.infer<typeof PlaybookVersionSchema>
21
+
22
+ export const PlaybookSchema = z.object({
23
+ id: recordIdSchema,
24
+ organizationId: recordIdSchema,
25
+ name: z.string().trim().min(1).max(200),
26
+ objective: z.string().trim().min(1).max(2000),
27
+ currentVersionId: recordIdSchema,
28
+ previousVersionId: recordIdSchema.optional(),
29
+ cycleCount: z.number().int().nonnegative().default(0),
30
+ createdAt: unixTimestampSchema,
31
+ updatedAt: unixTimestampSchema.optional(),
32
+ })
33
+ export type Playbook = z.infer<typeof PlaybookSchema>
@@ -0,0 +1,11 @@
1
+ import { z } from 'zod'
2
+
3
+ export const SignalDirectionSchema = z.enum(['produces', 'consumes'])
4
+ export type SignalDirection = z.infer<typeof SignalDirectionSchema>
5
+
6
+ export const SignalDeclarationSchema = z.object({
7
+ signalName: z.string().trim().min(1).max(200),
8
+ direction: SignalDirectionSchema,
9
+ description: z.string().trim().min(1).max(500).optional(),
10
+ })
11
+ export type SignalDeclaration = z.infer<typeof SignalDeclarationSchema>
@@ -3,8 +3,8 @@ import { z } from 'zod'
3
3
  import { baseChatMessageSchema } from './chat-api'
4
4
  import type { AnyChatMessage } from './chat-message'
5
5
  import {
6
- PlanArtifactKindSchema,
7
6
  PlanDraftSchema,
7
+ PlanNodeResultSubmissionSchema,
8
8
  PlanRunStatusSchema,
9
9
  SerializableExecutionPlanSchema,
10
10
  } from './execution-plan'
@@ -15,6 +15,8 @@ export const CONSULT_TEAM_TOOL_NAME = 'consultTeam' as const
15
15
  export const CREATE_EXECUTION_PLAN_TOOL_NAME = 'createExecutionPlan' as const
16
16
  export const REPLACE_EXECUTION_PLAN_TOOL_NAME = 'replaceExecutionPlan' as const
17
17
  export const SUBMIT_EXECUTION_NODE_RESULT_TOOL_NAME = 'submitExecutionNodeResult' as const
18
+ export const LIST_EXECUTION_PLANS_TOOL_NAME = 'listExecutionPlans' as const
19
+ export const GET_EXECUTION_PLAN_DETAILS_TOOL_NAME = 'getExecutionPlanDetails' as const
18
20
  export const GET_ACTIVE_EXECUTION_PLAN_TOOL_NAME = 'getActiveExecutionPlan' as const
19
21
  export const RESUME_EXECUTION_PLAN_RUN_TOOL_NAME = 'resumeExecutionPlanRun' as const
20
22
 
@@ -48,29 +50,6 @@ export const ConsultTeamResponseSchema = z
48
50
 
49
51
  export const ConsultTeamArgsSchema = z.object({ task: z.string().trim().min(1).max(6000) }).strict()
50
52
 
51
- const planStructuredPayloadSchema = z.union([z.record(z.string(), z.unknown()), z.array(z.unknown())])
52
-
53
- export const PlanArtifactSubmissionSchema = z
54
- .object({
55
- name: z.string().trim().min(1).max(200),
56
- kind: PlanArtifactKindSchema,
57
- pointer: z.string().trim().min(1).max(500),
58
- schemaRef: z.string().trim().min(1).max(200).optional(),
59
- description: z.string().trim().min(1).max(1000).optional(),
60
- payload: planStructuredPayloadSchema.optional(),
61
- })
62
- .strict()
63
- export type PlanArtifactSubmission = z.infer<typeof PlanArtifactSubmissionSchema>
64
-
65
- export const PlanNodeResultSubmissionSchema = z
66
- .object({
67
- structuredOutput: z.record(z.string(), z.unknown()).optional(),
68
- artifacts: z.array(PlanArtifactSubmissionSchema).default([]),
69
- notes: z.string().trim().min(1).max(2000).optional(),
70
- })
71
- .strict()
72
- export type PlanNodeResultSubmission = z.infer<typeof PlanNodeResultSubmissionSchema>
73
-
74
53
  const ExecutionPlanToolActionSchema = z.enum([
75
54
  'created',
76
55
  'replaced',
@@ -91,18 +70,41 @@ export const SubmitExecutionNodeResultArgsSchema = z
91
70
  .object({ runId: z.string().trim().min(1), nodeId: z.string().trim().min(1), result: PlanNodeResultSubmissionSchema })
92
71
  .strict()
93
72
 
73
+ export const ListExecutionPlansArgsSchema = z.object({}).strict()
74
+
94
75
  export const GetActiveExecutionPlanArgsSchema = z
95
76
  .object({
96
- includeEvents: z.boolean().optional().default(true),
97
- includeArtifacts: z.boolean().optional().default(true),
98
- includeApprovals: z.boolean().optional().default(true),
99
- includeCheckpoints: z.boolean().optional().default(false),
100
- includeValidationIssues: z.boolean().optional().default(true),
77
+ runId: z.string().trim().min(1).optional(),
78
+ includeEvents: z.boolean().default(true),
79
+ includeArtifacts: z.boolean().default(true),
80
+ includeApprovals: z.boolean().default(true),
81
+ includeCheckpoints: z.boolean().default(false),
82
+ includeValidationIssues: z.boolean().default(true),
101
83
  })
102
84
  .strict()
103
85
 
104
86
  export const ResumeExecutionPlanRunArgsSchema = z.object({ runId: z.string().trim().min(1) }).strict()
105
87
 
88
+ export const PlanSummarySchema = z
89
+ .object({ runId: z.string(), title: z.string(), status: PlanRunStatusSchema })
90
+ .strict()
91
+
92
+ export const ListExecutionPlansSummarySchema = z
93
+ .object({
94
+ runId: z.string(),
95
+ title: z.string(),
96
+ status: PlanRunStatusSchema,
97
+ objective: z.string(),
98
+ nodeCount: z.number().int().nonnegative(),
99
+ completedCount: z.number().int().nonnegative(),
100
+ failedCount: z.number().int().nonnegative(),
101
+ })
102
+ .strict()
103
+
104
+ export const ListExecutionPlansToolResultDataSchema = z
105
+ .object({ plans: z.array(ListExecutionPlansSummarySchema), totalCount: z.number().int().nonnegative() })
106
+ .strict()
107
+
106
108
  export const ExecutionPlanToolResultDataSchema = z
107
109
  .object({
108
110
  action: ExecutionPlanToolActionSchema,
@@ -111,6 +113,8 @@ export const ExecutionPlanToolResultDataSchema = z
111
113
  plan: SerializableExecutionPlanSchema.nullish(),
112
114
  hasPlan: z.boolean(),
113
115
  status: PlanRunStatusSchema.nullish(),
116
+ planCount: z.number().int().nonnegative().optional(),
117
+ planSummaries: z.array(PlanSummarySchema).optional(),
114
118
  })
115
119
  .strict()
116
120
 
@@ -128,6 +132,9 @@ export type ConsultTeamResultData = { responses: ConsultTeamResponseData[] }
128
132
  export type CreateExecutionPlanArgs = z.infer<typeof CreateExecutionPlanArgsSchema>
129
133
  export type ReplaceExecutionPlanArgs = z.infer<typeof ReplaceExecutionPlanArgsSchema>
130
134
  export type SubmitExecutionNodeResultArgs = z.infer<typeof SubmitExecutionNodeResultArgsSchema>
135
+ export type ListExecutionPlansArgs = z.infer<typeof ListExecutionPlansArgsSchema>
136
+ export type ListExecutionPlansSummary = z.infer<typeof ListExecutionPlansSummarySchema>
137
+ export type ListExecutionPlansToolResultData = z.infer<typeof ListExecutionPlansToolResultDataSchema>
131
138
  export type GetActiveExecutionPlanArgs = z.infer<typeof GetActiveExecutionPlanArgsSchema>
132
139
  export type ResumeExecutionPlanRunArgs = z.infer<typeof ResumeExecutionPlanRunArgsSchema>
133
140
  export type ExecutionPlanToolResultData = z.infer<typeof ExecutionPlanToolResultDataSchema>
@@ -138,6 +145,7 @@ export type CoreChatTools = {
138
145
  createExecutionPlan: { input: CreateExecutionPlanArgs; output: ExecutionPlanToolResultData }
139
146
  replaceExecutionPlan: { input: ReplaceExecutionPlanArgs; output: ExecutionPlanToolResultData }
140
147
  submitExecutionNodeResult: { input: SubmitExecutionNodeResultArgs; output: ExecutionPlanToolResultData }
141
- getActiveExecutionPlan: { input: GetActiveExecutionPlanArgs; output: ExecutionPlanToolResultData }
148
+ listExecutionPlans: { input: ListExecutionPlansArgs; output: ListExecutionPlansToolResultData }
149
+ getExecutionPlanDetails: { input: GetActiveExecutionPlanArgs; output: ExecutionPlanToolResultData }
142
150
  resumeExecutionPlanRun: { input: ResumeExecutionPlanRunArgs; output: ExecutionPlanToolResultData }
143
151
  }
@@ -28,17 +28,17 @@ export const sdkWorkstreamRecordSchema = z.object({
28
28
  organizationId: recordIdSchema,
29
29
  userId: recordIdSchema,
30
30
  agentId: z.string().nullish(),
31
- mode: sdkWorkstreamModeSchema.optional(),
32
- core: z.boolean().optional(),
31
+ mode: sdkWorkstreamModeSchema,
32
+ core: z.boolean(),
33
33
  coreType: z.string().nullish(),
34
34
  title: z.string().nullish(),
35
- status: sdkWorkstreamStatusSchema.nullish(),
35
+ status: sdkWorkstreamStatusSchema,
36
36
  memoryBlock: z.string().nullish(),
37
37
  memoryBlockSummary: z.string().nullish(),
38
38
  activeRunId: z.string().nullish(),
39
39
  compactionSummary: z.string().nullish(),
40
40
  lastCompactedMessageId: z.string().nullish(),
41
- nameGenerated: z.boolean().optional(), // Ideally `isNameGenerated`, but maps directly to SurrealDB column `nameGenerated`
41
+ nameGenerated: z.boolean(), // Ideally `isNameGenerated`, but maps directly to SurrealDB column `nameGenerated`
42
42
  isCompacting: z.boolean().optional(),
43
43
  state: z.unknown().optional(),
44
44
  createdAt: z.coerce.date(),
@@ -0,0 +1,18 @@
1
+ import type { ConfidenceScore } from '../schemas/confidence'
2
+
3
+ export function aggregateConfidence(
4
+ scores: ConfidenceScore[],
5
+ method?: 'weighted-average' | 'min' | 'bayesian',
6
+ ): number {
7
+ if (scores.length === 0) return 0
8
+ const resolvedMethod = method ?? 'weighted-average'
9
+ const overalls = scores.map((s) => s.overall)
10
+ switch (resolvedMethod) {
11
+ case 'weighted-average':
12
+ return overalls.reduce((a, b) => a + b, 0) / overalls.length
13
+ case 'min':
14
+ return Math.min(...overalls)
15
+ case 'bayesian':
16
+ return overalls.reduce((a, b) => a * b, 1)
17
+ }
18
+ }
@@ -0,0 +1,34 @@
1
+ export function toIsoDateTimeString(value: unknown): string {
2
+ if (value instanceof Date) {
3
+ return value.toISOString()
4
+ }
5
+
6
+ // Assume API boundaries already use ISO strings.
7
+ if (typeof value === 'string') {
8
+ return value
9
+ }
10
+
11
+ // Support unix timestamps (seconds or milliseconds).
12
+ if (typeof value === 'number') {
13
+ const millis = value < 1_000_000_000_000 ? value * 1000 : value
14
+ return new Date(millis).toISOString()
15
+ }
16
+
17
+ // Support objects that expose toISOString (e.g., SurrealDB temporal types).
18
+ if (value && typeof value === 'object') {
19
+ const maybeToIso = (value as { toISOString?: unknown }).toISOString
20
+ if (typeof maybeToIso === 'function') {
21
+ return (value as { toISOString: () => string }).toISOString()
22
+ }
23
+ }
24
+
25
+ return String(value)
26
+ }
27
+
28
+ export function toOptionalIsoDateTimeString(value: unknown): string | undefined {
29
+ if (value === null || value === undefined || value === '') {
30
+ return undefined
31
+ }
32
+
33
+ return toIsoDateTimeString(value)
34
+ }
@@ -0,0 +1,10 @@
1
+ export function getErrorMessage(error: unknown): string {
2
+ if (error instanceof Error) return error.message
3
+ if (typeof error === 'string') return error
4
+
5
+ try {
6
+ return JSON.stringify(error)
7
+ } catch {
8
+ return String(error)
9
+ }
10
+ }