@lota-sdk/shared 0.1.15 → 0.1.17
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 +3 -3
- package/src/constants/model.ts +34 -0
- package/src/constants/search.ts +1 -0
- package/src/index.ts +11 -0
- package/src/runtime/agent-types.ts +2 -0
- package/src/runtime/chat-message-metadata.ts +19 -9
- package/src/runtime/execution-plan-result.ts +20 -0
- package/src/schemas/chat-message.ts +0 -3
- package/src/schemas/common.ts +2 -0
- package/src/schemas/confidence.ts +20 -0
- package/src/schemas/execution-plan.ts +454 -31
- package/src/schemas/graph-designer.ts +21 -0
- package/src/schemas/playbook.ts +33 -0
- package/src/schemas/plugin-coordination.ts +11 -0
- package/src/schemas/tools.ts +38 -30
- package/src/schemas/workstream.ts +4 -4
- package/src/utils/confidence.ts +18 -0
- package/src/utils/date-time.ts +34 -0
- package/src/utils/errors.ts +10 -0
- package/src/utils/slack-social-reply.ts +64 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lota-sdk/shared",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
"scripts": {
|
|
18
|
-
"lint": "
|
|
18
|
+
"lint": "bunx oxlint --fix -c ../oxlint.config.ts src",
|
|
19
19
|
"format": "bunx oxfmt src",
|
|
20
20
|
"typecheck": "bunx tsgo --noEmit",
|
|
21
21
|
"test:unit": "bun test ../tests/unit/shared"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"registry": "https://registry.npmjs.org/"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"ai": "^6.0.
|
|
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' as const
|
|
5
|
+
export const OPENROUTER_DELEGATED_REASONING_MODEL_ID = 'openrouter/google/gemini-3-flash-preview' 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:nitro' 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,12 @@ 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'
|
|
32
|
+
export * from './utils/slack-social-reply'
|
|
22
33
|
export * from './utils/string'
|
|
@@ -6,9 +6,11 @@ export interface CreateRoutedAgentOptions<TTools extends ToolSet = ToolSet> {
|
|
|
6
6
|
mode: ChatMode
|
|
7
7
|
tools: TTools
|
|
8
8
|
extraInstructions?: string
|
|
9
|
+
headers?: Record<string, string>
|
|
9
10
|
stopWhen?: StopCondition<TTools> | Array<StopCondition<TTools>>
|
|
10
11
|
prepareStep?: PrepareStepFunction<TTools>
|
|
11
12
|
maxRetries?: number
|
|
13
|
+
output?: Output.Output
|
|
12
14
|
modelOverride?: { model: unknown; providerOptions?: Record<string, unknown> }
|
|
13
15
|
onFinish?: ToolLoopAgentOnFinishCallback<TTools>
|
|
14
16
|
}
|
|
@@ -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
|
-
|
|
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
|
-
|
|
35
|
+
createdAt?: number,
|
|
29
36
|
): NonNullable<TMetadata> & { createdAt: number } {
|
|
30
|
-
const next =
|
|
31
|
-
metadata && typeof metadata === 'object'
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
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
|
-
|
|
54
|
+
createdAt?: number,
|
|
45
55
|
): TMessage {
|
|
46
|
-
const metadata = withCreatedAtMetadata(message.metadata,
|
|
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
|
+
}
|
|
@@ -7,9 +7,6 @@ export const messageMetadataSchema = z
|
|
|
7
7
|
.object({
|
|
8
8
|
agentId: z.string().optional(),
|
|
9
9
|
agentName: z.string().optional(),
|
|
10
|
-
reasoningProfile: z.enum(['fast', 'standard', 'deep']).optional(),
|
|
11
|
-
highImpactClasses: z.array(z.string()).optional(),
|
|
12
|
-
policyClasses: z.array(z.string()).optional(),
|
|
13
10
|
semanticTerminationReason: z.enum(['none', 'conflict', 'cycle-detected']).optional(),
|
|
14
11
|
inputTokens: z.number().optional(),
|
|
15
12
|
outputTokens: z.number().optional(),
|
package/src/schemas/common.ts
CHANGED
|
@@ -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
|
-
|
|
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([
|
|
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([
|
|
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
|
-
|
|
148
|
-
|
|
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
|
|
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:
|
|
265
|
-
updatedAt:
|
|
266
|
-
compiledAt:
|
|
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:
|
|
293
|
-
updatedAt:
|
|
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
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
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
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
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:
|
|
666
|
+
structuredOutput: planStructuredObjectSchema.optional(),
|
|
347
667
|
notes: z.string().optional(),
|
|
348
668
|
validationIssueIds: z.array(recordIdSchema).default([]),
|
|
349
669
|
failureClass: PlanFailureClassSchema.optional(),
|
|
350
|
-
createdAt:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
411
|
-
updatedAt:
|
|
412
|
-
respondedAt:
|
|
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:
|
|
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>
|
package/src/schemas/tools.ts
CHANGED
|
@@ -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
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
-
|
|
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
|
|
32
|
-
core: z.boolean()
|
|
31
|
+
mode: sdkWorkstreamModeSchema,
|
|
32
|
+
core: z.boolean(),
|
|
33
33
|
coreType: z.string().nullish(),
|
|
34
34
|
title: z.string().nullish(),
|
|
35
|
-
status: sdkWorkstreamStatusSchema
|
|
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()
|
|
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,64 @@
|
|
|
1
|
+
import { normalizeAssistantMarkdown } from './markdown-normalization'
|
|
2
|
+
|
|
3
|
+
const LEADING_TOOL_NOTICE_BLOCK_PATTERN = /^```(?:md|markdown|text)?\nAgent executed[\s\S]*?tools?\.\n```\n{0,2}/
|
|
4
|
+
|
|
5
|
+
const TOOL_DISPLAY_NAME_OVERRIDES: Record<string, string> = {
|
|
6
|
+
consultSpecialist: 'Consult Specialist',
|
|
7
|
+
fetchWebpage: 'Fetch Webpage',
|
|
8
|
+
memoryRemember: 'Remember Memory',
|
|
9
|
+
memorySearch: 'Memory Search',
|
|
10
|
+
researchTopic: 'Research Topic',
|
|
11
|
+
searchWeb: 'Web Search',
|
|
12
|
+
userQuestions: 'User Questions',
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function titleCaseWord(value: string): string {
|
|
16
|
+
const firstCharacter = value.at(0)
|
|
17
|
+
return firstCharacter ? firstCharacter.toUpperCase() + value.slice(1).toLowerCase() : value
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function formatQuotedDisplayNameList(values: string[]): string {
|
|
21
|
+
if (values.length === 0) return ''
|
|
22
|
+
if (values.length === 1) return `"${values[0]}"`
|
|
23
|
+
if (values.length === 2) return `"${values[0]}" and "${values[1]}"`
|
|
24
|
+
|
|
25
|
+
const allButLast = values
|
|
26
|
+
.slice(0, -1)
|
|
27
|
+
.map((value) => `"${value}"`)
|
|
28
|
+
.join(', ')
|
|
29
|
+
const lastValue = values.at(-1)
|
|
30
|
+
return lastValue ? `${allButLast}, and "${lastValue}"` : allButLast
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function humanizeToolDisplayName(toolName: string): string {
|
|
34
|
+
const override = TOOL_DISPLAY_NAME_OVERRIDES[toolName]
|
|
35
|
+
if (override) return override
|
|
36
|
+
|
|
37
|
+
return toolName
|
|
38
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
39
|
+
.replace(/[_-]+/g, ' ')
|
|
40
|
+
.trim()
|
|
41
|
+
.split(/\s+/)
|
|
42
|
+
.filter(Boolean)
|
|
43
|
+
.map(titleCaseWord)
|
|
44
|
+
.join(' ')
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function buildSlackToolExecutionNoticeMarkdown(toolNames: string[]): string {
|
|
48
|
+
const uniqueDisplayNames = [...new Set(toolNames.map(humanizeToolDisplayName).filter((value) => value.length > 0))]
|
|
49
|
+
if (uniqueDisplayNames.length === 0) return ''
|
|
50
|
+
|
|
51
|
+
const toolLabel = uniqueDisplayNames.length === 1 ? 'tool' : 'tools'
|
|
52
|
+
return `\`\`\`\nAgent executed ${formatQuotedDisplayNameList(uniqueDisplayNames)} ${toolLabel}.\n\`\`\``
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function stripSlackToolExecutionNoticeMarkdown(markdown: string): string {
|
|
56
|
+
return markdown.replace(LEADING_TOOL_NOTICE_BLOCK_PATTERN, '').trim()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function buildSlackSocialReplyMarkdown(params: { replyMarkdown: string; executedToolNames?: string[] }): string {
|
|
60
|
+
const normalizedReply = normalizeAssistantMarkdown(params.replyMarkdown).trim()
|
|
61
|
+
const toolNoticeMarkdown = buildSlackToolExecutionNoticeMarkdown(params.executedToolNames ?? [])
|
|
62
|
+
|
|
63
|
+
return [toolNoticeMarkdown, normalizedReply].filter((value) => value.length > 0).join('\n\n')
|
|
64
|
+
}
|