@lota-sdk/core 0.1.16 → 0.1.18
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 +6 -3
- package/src/ai/definitions.ts +1 -1
- package/src/ai/embedding-cache.ts +2 -4
- package/src/{bifrost/bifrost.ts → ai-gateway/ai-gateway.ts} +115 -79
- package/src/ai-gateway/cache-headers.ts +8 -0
- package/src/ai-gateway/index.ts +2 -0
- package/src/config/model-constants.ts +1 -1
- package/src/create-runtime.ts +26 -1
- package/src/db/memory-store.helpers.ts +1 -3
- package/src/db/schema-fingerprint.ts +1 -3
- package/src/embeddings/provider.ts +2 -2
- package/src/index.ts +1 -1
- package/src/queues/document-processor.queue.ts +2 -4
- package/src/queues/post-chat-memory.queue.ts +8 -2
- package/src/queues/recent-activity-title-refinement.queue.ts +1 -1
- package/src/queues/skill-extraction.queue.ts +1 -1
- package/src/queues/workstream-title-generation.queue.ts +1 -1
- package/src/redis/redis-lease-lock.ts +1 -2
- package/src/runtime/agent-runtime-policy.ts +3 -14
- package/src/runtime/context-compaction.ts +2 -4
- package/src/runtime/index.ts +1 -1
- package/src/runtime/runtime-config.ts +87 -7
- package/src/runtime/runtime-extensions.ts +0 -1
- package/src/runtime/social-chat.ts +752 -0
- package/src/runtime/team-consultation-orchestrator.ts +0 -4
- package/src/services/agent-executor.service.ts +0 -1
- package/src/services/document-chunk.service.ts +1 -3
- package/src/services/index.ts +1 -0
- package/src/services/memory.service.ts +7 -2
- package/src/services/recent-activity.service.ts +1 -3
- package/src/services/social-chat-history.service.ts +197 -0
- package/src/services/workstream-message.service.ts +1 -3
- package/src/services/workstream-turn-preparation.service.ts +0 -23
- package/src/system-agents/context-compaction.agent.ts +4 -2
- package/src/system-agents/delegated-agent-factory.ts +3 -0
- package/src/system-agents/memory-reranker.agent.ts +5 -3
- package/src/system-agents/memory.agent.ts +4 -2
- package/src/system-agents/recent-activity-title-refiner.agent.ts +4 -2
- package/src/system-agents/regular-chat-memory-digest.agent.ts +4 -2
- package/src/system-agents/skill-extractor.agent.ts +4 -2
- package/src/system-agents/skill-manager.agent.ts +4 -2
- package/src/system-agents/title-generator.agent.ts +4 -2
- package/src/tools/research-topic.tool.ts +4 -2
- package/src/tools/team-think.tool.ts +0 -3
- package/src/workers/regular-chat-memory-digest.helpers.ts +1 -1
- package/src/workers/regular-chat-memory-digest.runner.ts +43 -10
- package/src/workers/skill-extraction.runner.ts +25 -5
- package/src/workers/utils/repo-structure-extractor.ts +2 -2
- package/src/workers/utils/workstream-message-query.ts +3 -5
- package/src/bifrost/index.ts +0 -1
- package/src/runtime/workstream-routing-policy.ts +0 -267
|
@@ -15,6 +15,8 @@ interface PostChatMemoryExtractionJob {
|
|
|
15
15
|
orgId: string
|
|
16
16
|
workstreamId: string
|
|
17
17
|
sourceId: string
|
|
18
|
+
source?: string
|
|
19
|
+
sourceMetadata?: Record<string, unknown>
|
|
18
20
|
onboardStatus?: OrganizationOnboardStatus
|
|
19
21
|
userMessage: string
|
|
20
22
|
historyMessages: PostChatMemoryMessage[]
|
|
@@ -54,6 +56,8 @@ async function processPostChatMemoryJob(job: Job<PostChatMemoryExtractionJob>):
|
|
|
54
56
|
input: userMessage,
|
|
55
57
|
output: joinedOutput,
|
|
56
58
|
sourceId: data.sourceId,
|
|
59
|
+
source: data.source,
|
|
60
|
+
sourceMetadata: data.sourceMetadata,
|
|
57
61
|
onboardStatus: data.onboardStatus,
|
|
58
62
|
...(uniqueAgentNames.length > 0 ? { agentName: uniqueAgentNames[0] } : {}),
|
|
59
63
|
historyMessages: data.historyMessages,
|
|
@@ -67,7 +71,7 @@ const postChatMemory = createQueueFactory<PostChatMemoryExtractionJob>({
|
|
|
67
71
|
name: 'post-chat-memory',
|
|
68
72
|
displayName: 'Post-chat memory',
|
|
69
73
|
jobName: 'extract-memory',
|
|
70
|
-
concurrency:
|
|
74
|
+
concurrency: 10,
|
|
71
75
|
lockDuration: 900_000,
|
|
72
76
|
maxStalledCount: 10,
|
|
73
77
|
stalledInterval: 120_000,
|
|
@@ -75,7 +79,9 @@ const postChatMemory = createQueueFactory<PostChatMemoryExtractionJob>({
|
|
|
75
79
|
processor: processPostChatMemoryJob,
|
|
76
80
|
})
|
|
77
81
|
|
|
78
|
-
export
|
|
82
|
+
export function enqueuePostChatMemory(job: PostChatMemoryExtractionJob, options?: { dedupeKey?: string }) {
|
|
83
|
+
return postChatMemory.enqueue(job, options?.dedupeKey ? { jobId: options.dedupeKey } : undefined)
|
|
84
|
+
}
|
|
79
85
|
export const startPostChatMemoryWorker = postChatMemory.startWorker
|
|
80
86
|
|
|
81
87
|
if (import.meta.main) {
|
|
@@ -17,7 +17,7 @@ const recentActivityTitleRefinement = createQueueFactory<RecentActivityTitleRefi
|
|
|
17
17
|
name: 'recent-activity-title-refinement',
|
|
18
18
|
displayName: 'Recent activity title refinement',
|
|
19
19
|
jobName: 'refine-recent-activity-title',
|
|
20
|
-
concurrency:
|
|
20
|
+
concurrency: 10,
|
|
21
21
|
lockDuration: 300_000,
|
|
22
22
|
defaultJobOptions: { attempts: 3, backoff: { type: 'exponential', delay: 2_000 } },
|
|
23
23
|
processor: processRecentActivityTitleRefinementJob,
|
|
@@ -10,7 +10,7 @@ const skillExtraction = createQueueFactory<SkillExtractionJob>({
|
|
|
10
10
|
name: 'skill-extraction',
|
|
11
11
|
displayName: 'Skill extraction',
|
|
12
12
|
jobName: 'run-extraction',
|
|
13
|
-
concurrency:
|
|
13
|
+
concurrency: 10,
|
|
14
14
|
lockDuration: 600_000,
|
|
15
15
|
defaultJobOptions: { attempts: 2, backoff: { type: 'exponential', delay: 5000 } },
|
|
16
16
|
processorPath: getWorkerPath('skill-extraction.worker.ts'),
|
|
@@ -20,7 +20,7 @@ const workstreamTitleGeneration = createQueueFactory<WorkstreamTitleGenerationJo
|
|
|
20
20
|
name: 'workstream-title-generation',
|
|
21
21
|
displayName: 'Workstream title generation',
|
|
22
22
|
jobName: 'generate-workstream-title',
|
|
23
|
-
concurrency:
|
|
23
|
+
concurrency: 10,
|
|
24
24
|
lockDuration: 60_000,
|
|
25
25
|
defaultJobOptions: { attempts: 2, backoff: { type: 'exponential', delay: 2_000 } },
|
|
26
26
|
processor: processWorkstreamTitleGenerationJob,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto'
|
|
2
1
|
import { setTimeout as delay } from 'node:timers/promises'
|
|
3
2
|
|
|
4
3
|
import type IORedis from 'ioredis'
|
|
@@ -147,7 +146,7 @@ export async function withRedisLeaseLock<T>(
|
|
|
147
146
|
const heldInfoThresholdMs = options.heldInfoThresholdMs ?? 5_000
|
|
148
147
|
const label = options.label ?? 'redis lease lock'
|
|
149
148
|
|
|
150
|
-
const lockValue = randomUUID()
|
|
149
|
+
const lockValue = crypto.randomUUID()
|
|
151
150
|
const waitStart = Date.now()
|
|
152
151
|
await acquireLeaseLock({ ...options, lockKey, lockValue, label, retryDelayMs, waitLogIntervalMs, maxWaitMs })
|
|
153
152
|
const waitedMs = Date.now() - waitStart
|
|
@@ -3,18 +3,12 @@ import type { ExecutionMode, PlanArtifactSubmission, PlanNodeSpec } from '@lota-
|
|
|
3
3
|
import { getLeadAgentId } from '../config/agent-defaults'
|
|
4
4
|
import { resolveOnboardingOwnerAgentId } from '../config/workstream-defaults'
|
|
5
5
|
import type { ChatMode } from './agent-types'
|
|
6
|
-
import { resolveReasoningProfile } from './workstream-routing-policy'
|
|
7
|
-
import type { ReasoningProfileName } from './workstream-routing-policy'
|
|
8
|
-
|
|
9
6
|
export interface AgentRuntimeConfig<TAgent extends string> {
|
|
10
7
|
id: TAgent
|
|
11
8
|
displayName: string
|
|
12
9
|
mode: ChatMode
|
|
13
10
|
extraInstructions?: string
|
|
14
11
|
maxSteps: number
|
|
15
|
-
reasoningProfile: ReasoningProfileName
|
|
16
|
-
toolCallBudget: number
|
|
17
|
-
maxInputTokensHint: number
|
|
18
12
|
}
|
|
19
13
|
|
|
20
14
|
export interface AgentToolPolicy<TSkill extends PropertyKey> {
|
|
@@ -100,7 +94,6 @@ export function buildAgentRuntimeConfig<TAgent extends string, TSkill extends Pr
|
|
|
100
94
|
skills?: TSkill[]
|
|
101
95
|
onboardingActive: boolean
|
|
102
96
|
linearInstalled: boolean
|
|
103
|
-
reasoningProfile?: ReasoningProfileName
|
|
104
97
|
systemWorkspaceDetails?: string
|
|
105
98
|
preSeededMemoriesSection?: string
|
|
106
99
|
retrievedKnowledgeSection?: string
|
|
@@ -115,7 +108,6 @@ export function buildAgentRuntimeConfig<TAgent extends string, TSkill extends Pr
|
|
|
115
108
|
buildOnboardingPromptSection: () => string
|
|
116
109
|
}): AgentRuntimeConfig<TAgent> {
|
|
117
110
|
const mode = params.mode ?? toChatMode(params.workstreamMode)
|
|
118
|
-
const profile = resolveReasoningProfile({ message: '', explicitProfile: params.reasoningProfile ?? 'standard' })
|
|
119
111
|
const rulesSection = params.buildGlobalRuleInstructionSection()
|
|
120
112
|
const skillsSection =
|
|
121
113
|
params.skills && params.skills.length > 0 ? params.buildSkillInstructionSection(params.skills) : ''
|
|
@@ -141,10 +133,7 @@ export function buildAgentRuntimeConfig<TAgent extends string, TSkill extends Pr
|
|
|
141
133
|
displayName: params.displayNameByAgent[params.agentId] ?? params.agentId,
|
|
142
134
|
mode,
|
|
143
135
|
extraInstructions,
|
|
144
|
-
maxSteps:
|
|
145
|
-
reasoningProfile: profile.name,
|
|
146
|
-
toolCallBudget: profile.toolCallBudget,
|
|
147
|
-
maxInputTokensHint: profile.maxInputTokensHint,
|
|
136
|
+
maxSteps: 15,
|
|
148
137
|
}
|
|
149
138
|
}
|
|
150
139
|
|
|
@@ -180,8 +169,8 @@ export function buildWorkstreamAgentToolPolicy<TAgent extends string, TSkill ext
|
|
|
180
169
|
includeReadFileParts: true,
|
|
181
170
|
includeInspectWebsite: params.onboardingActive && params.agentId === onboardingOwnerAgentId,
|
|
182
171
|
includeProceedInOnboarding: params.onboardingActive && params.agentId === onboardingOwnerAgentId,
|
|
183
|
-
includeGithubIntegration: params.
|
|
184
|
-
includeIndexRepositoryByURL: params.
|
|
172
|
+
includeGithubIntegration: params.agentId === onboardingOwnerAgentId,
|
|
173
|
+
includeIndexRepositoryByURL: params.agentId === onboardingOwnerAgentId,
|
|
185
174
|
includeIndexedRepository: params.githubInstalled && params.provideRepoTool,
|
|
186
175
|
}
|
|
187
176
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { createHash, randomUUID } from 'node:crypto'
|
|
2
|
-
|
|
3
1
|
import type { ChatMessage } from '@lota-sdk/shared'
|
|
4
2
|
|
|
5
3
|
import { CHARS_PER_TOKEN_ESTIMATE, compactWhitespace, readRecord, readString, stringifyUnknown } from '../utils/string'
|
|
@@ -108,7 +106,7 @@ function createStableId(prefix: string, ...parts: Array<string | number | undefi
|
|
|
108
106
|
.map((part) => (part === undefined ? '' : String(part)))
|
|
109
107
|
.map((part) => compactWhitespace(part))
|
|
110
108
|
.join('|')
|
|
111
|
-
const hash =
|
|
109
|
+
const hash = new Bun.CryptoHasher('sha1').update(`${prefix}|${payload}`).digest('hex').slice(0, 20)
|
|
112
110
|
return `${prefix}_${hash}`
|
|
113
111
|
}
|
|
114
112
|
|
|
@@ -532,7 +530,7 @@ export function createContextCompactionRuntime(
|
|
|
532
530
|
options: CreateContextCompactionRuntimeOptions,
|
|
533
531
|
): ContextCompactionRuntime {
|
|
534
532
|
const now = options.now ?? (() => Date.now())
|
|
535
|
-
const randomId = options.randomId ?? (() => randomUUID())
|
|
533
|
+
const randomId = options.randomId ?? (() => crypto.randomUUID())
|
|
536
534
|
const thresholdRatio = options.thresholdRatio ?? CONTEXT_COMPACTION_THRESHOLD_RATIO
|
|
537
535
|
const outputReserveTokens = options.outputReserveTokens ?? CONTEXT_OUTPUT_RESERVE_TOKENS
|
|
538
536
|
const safetyMarginTokens = options.safetyMarginTokens ?? CONTEXT_SAFETY_MARGIN_TOKENS
|
package/src/runtime/index.ts
CHANGED
|
@@ -20,11 +20,11 @@ export * from './runtime-config'
|
|
|
20
20
|
export * from './runtime-extensions'
|
|
21
21
|
export * from './runtime-worker-registry'
|
|
22
22
|
export * from './skill-extraction-policy'
|
|
23
|
+
export * from './social-chat'
|
|
23
24
|
export * from './team-consultation-orchestrator'
|
|
24
25
|
export * from './team-consultation-prompts'
|
|
25
26
|
export * from './turn-lifecycle'
|
|
26
27
|
export * from './workstream-chat-helpers'
|
|
27
|
-
export * from './workstream-routing-policy'
|
|
28
28
|
export {
|
|
29
29
|
WorkstreamStateSchema,
|
|
30
30
|
type WorkstreamState,
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import type { ToolSet } from 'ai'
|
|
1
2
|
import { z } from 'zod'
|
|
2
3
|
|
|
3
4
|
import type { CoreWorkstreamProfile } from '../config/agent-defaults'
|
|
4
5
|
import type { AgentFactory, AgentRuntimeConfigProvider, AgentToolBuilder } from '../config/agent-types'
|
|
5
6
|
import type { LotaWorkstreamConfig, WorkstreamBootstrapWelcomeConfig } from '../config/workstream-defaults'
|
|
7
|
+
import type { RecordIdRef } from '../db/record-id'
|
|
6
8
|
import type { NotificationService } from '../services/notification.service'
|
|
7
9
|
import { isRecord } from '../utils/string'
|
|
8
10
|
import type { GraphDesigner } from './graph-designer'
|
|
@@ -61,6 +63,87 @@ function isWorkerExtensionRecord(value: unknown): value is LotaRuntimeWorkerExte
|
|
|
61
63
|
return true
|
|
62
64
|
}
|
|
63
65
|
|
|
66
|
+
export interface LotaSocialChatSlackConfig {
|
|
67
|
+
botToken?: string
|
|
68
|
+
signingSecret?: string
|
|
69
|
+
userName?: string
|
|
70
|
+
dedupeTtlMs?: number
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface LotaSocialChatResolveContextParams {
|
|
74
|
+
platform: 'slack'
|
|
75
|
+
channelId: string
|
|
76
|
+
threadId: string
|
|
77
|
+
messageId: string
|
|
78
|
+
text: string
|
|
79
|
+
authorId?: string
|
|
80
|
+
authorName?: string
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface LotaSocialChatResolvedContext {
|
|
84
|
+
workspaceId: RecordIdRef
|
|
85
|
+
userId: RecordIdRef
|
|
86
|
+
userName?: string | null
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface BuildSocialChatAgentToolsParams {
|
|
90
|
+
agentId: string
|
|
91
|
+
workspaceId: RecordIdRef
|
|
92
|
+
workspaceIdString: string
|
|
93
|
+
userId: RecordIdRef
|
|
94
|
+
userIdString: string
|
|
95
|
+
userName?: string | null
|
|
96
|
+
platform: 'slack'
|
|
97
|
+
channelId: string
|
|
98
|
+
threadId: string
|
|
99
|
+
incomingMessageId: string
|
|
100
|
+
incomingText: string
|
|
101
|
+
memoryBlock: string
|
|
102
|
+
onAppendMemoryBlock: (value: string) => void
|
|
103
|
+
context?: Record<string, unknown> | null
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface LotaRuntimeSocialChatConfig {
|
|
107
|
+
agentId?: string
|
|
108
|
+
agentDisplayName?: string
|
|
109
|
+
slack?: LotaSocialChatSlackConfig
|
|
110
|
+
historyRedisKeyPrefix?: string
|
|
111
|
+
stateRedisKeyPrefix?: string
|
|
112
|
+
resolveContext: (
|
|
113
|
+
params: LotaSocialChatResolveContextParams,
|
|
114
|
+
) => LotaSocialChatResolvedContext | Promise<LotaSocialChatResolvedContext>
|
|
115
|
+
buildAgentTools: (params: BuildSocialChatAgentToolsParams) => ToolSet | Promise<ToolSet>
|
|
116
|
+
getConsultParticipants?:
|
|
117
|
+
| ((params: {
|
|
118
|
+
workspaceId: RecordIdRef
|
|
119
|
+
workspaceIdString: string
|
|
120
|
+
platform: 'slack'
|
|
121
|
+
}) => string[] | Promise<string[]>)
|
|
122
|
+
| undefined
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function isSlackSocialChatConfig(value: unknown): value is LotaSocialChatSlackConfig {
|
|
126
|
+
if (!isRecord(value)) return false
|
|
127
|
+
if (value.botToken !== undefined && typeof value.botToken !== 'string') return false
|
|
128
|
+
if (value.signingSecret !== undefined && typeof value.signingSecret !== 'string') return false
|
|
129
|
+
if (value.userName !== undefined && typeof value.userName !== 'string') return false
|
|
130
|
+
if (value.dedupeTtlMs !== undefined && typeof value.dedupeTtlMs !== 'number') return false
|
|
131
|
+
return true
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function isSocialChatConfig(value: unknown): value is LotaRuntimeSocialChatConfig {
|
|
135
|
+
if (!isRecord(value)) return false
|
|
136
|
+
if (value.agentId !== undefined && typeof value.agentId !== 'string') return false
|
|
137
|
+
if (value.agentDisplayName !== undefined && typeof value.agentDisplayName !== 'string') return false
|
|
138
|
+
if (value.historyRedisKeyPrefix !== undefined && typeof value.historyRedisKeyPrefix !== 'string') return false
|
|
139
|
+
if (value.stateRedisKeyPrefix !== undefined && typeof value.stateRedisKeyPrefix !== 'string') return false
|
|
140
|
+
if (value.slack !== undefined && !isSlackSocialChatConfig(value.slack)) return false
|
|
141
|
+
if (!isFunction(value.resolveContext)) return false
|
|
142
|
+
if (!isFunction(value.buildAgentTools)) return false
|
|
143
|
+
if (value.getConsultParticipants !== undefined && !isFunction(value.getConsultParticipants)) return false
|
|
144
|
+
return true
|
|
145
|
+
}
|
|
146
|
+
|
|
64
147
|
const workstreamBootstrapWelcomeConfigSchema = z.object({
|
|
65
148
|
directAgentId: z.string().trim().min(1),
|
|
66
149
|
buildMessageText: z.custom<WorkstreamBootstrapWelcomeConfig['buildMessageText']>(isFunction, {
|
|
@@ -137,8 +220,6 @@ export const LotaRuntimeConfigSchema = z.object({
|
|
|
137
220
|
aiGateway: z.object({
|
|
138
221
|
url: z.string().trim().min(1),
|
|
139
222
|
key: z.string().trim().min(1),
|
|
140
|
-
admin: z.string().trim().min(1).optional(),
|
|
141
|
-
pass: z.string().trim().min(1).optional(),
|
|
142
223
|
embeddingModel: z.string().trim().min(1).default('openai/text-embedding-3-small'),
|
|
143
224
|
}),
|
|
144
225
|
s3: z.object({
|
|
@@ -161,9 +242,9 @@ export const LotaRuntimeConfigSchema = z.object({
|
|
|
161
242
|
memory: z
|
|
162
243
|
.object({
|
|
163
244
|
searchK: z.coerce.number().int().positive().default(6),
|
|
164
|
-
embeddingCacheTtlSeconds: z.coerce.number().int().positive().default(
|
|
245
|
+
embeddingCacheTtlSeconds: z.coerce.number().int().positive().default(7200),
|
|
165
246
|
})
|
|
166
|
-
.default({ searchK: 6, embeddingCacheTtlSeconds:
|
|
247
|
+
.default({ searchK: 6, embeddingCacheTtlSeconds: 7200 }),
|
|
167
248
|
workstreams: workstreamConfigSchema.default({}),
|
|
168
249
|
backgroundProcessing: z
|
|
169
250
|
.object({
|
|
@@ -188,6 +269,7 @@ export const LotaRuntimeConfigSchema = z.object({
|
|
|
188
269
|
runtimeAdapters: z.custom<LotaRuntimeAdapters>(isRecord).optional(),
|
|
189
270
|
turnHooks: z.custom<LotaRuntimeTurnHooks>(isRecord).optional(),
|
|
190
271
|
graphDesigner: z.custom<GraphDesigner>(isGraphDesigner).optional(),
|
|
272
|
+
socialChat: z.custom<LotaRuntimeSocialChatConfig>(isSocialChatConfig).optional(),
|
|
191
273
|
})
|
|
192
274
|
|
|
193
275
|
export type LotaRuntimeConfig = z.input<typeof LotaRuntimeConfigSchema>
|
|
@@ -210,9 +292,7 @@ export const LOTA_RUNTIME_ENV_KEYS = Object.freeze([
|
|
|
210
292
|
'SURREALDB_PASSWORD',
|
|
211
293
|
'REDIS_URL',
|
|
212
294
|
'AI_GATEWAY_URL',
|
|
213
|
-
'
|
|
214
|
-
'AI_GATEWAY_ADMIN',
|
|
215
|
-
'AI_GATEWAY_PASS',
|
|
295
|
+
'LOTA_KEY',
|
|
216
296
|
'AI_EMBEDDING_MODEL',
|
|
217
297
|
'S3_ENDPOINT',
|
|
218
298
|
'S3_BUCKET',
|
|
@@ -123,7 +123,6 @@ export interface ResolveAgentParams {
|
|
|
123
123
|
onboardingActive: boolean
|
|
124
124
|
linearInstalled: boolean
|
|
125
125
|
githubInstalled: boolean
|
|
126
|
-
reasoningProfile: string
|
|
127
126
|
skills?: string[]
|
|
128
127
|
additionalInstructionSections?: string[]
|
|
129
128
|
context: Record<string, unknown> | null
|