d25d482dc2
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
119 lines
3.8 KiB
TypeScript
119 lines
3.8 KiB
TypeScript
/**
|
|
* Reuses the Agent block's skills and memory subsystems for Pi runs. Skills
|
|
* resolve to full `{ name, content }` entries (so a backend can surface them as
|
|
* Pi skills), and multi-turn memory goes through the shared `memoryService`
|
|
* keyed by `memoryType`/`conversationId` — seeding the run and persisting the
|
|
* user task plus the agent's final message.
|
|
*/
|
|
|
|
import { createLogger } from '@sim/logger'
|
|
import { getErrorMessage } from '@sim/utils/errors'
|
|
import { memoryService } from '@/executor/handlers/agent/memory'
|
|
import { resolveSkillContentById } from '@/executor/handlers/agent/skills-resolver'
|
|
import type { AgentInputs, Message, SkillInput } from '@/executor/handlers/agent/types'
|
|
import type { PiMessage, PiSkill } from '@/executor/handlers/pi/backend'
|
|
import type { ExecutionContext } from '@/executor/types'
|
|
|
|
const logger = createLogger('PiContext')
|
|
|
|
/** Memory configuration — the Agent block's memory input fields, reused as-is. */
|
|
export type PiMemoryConfig = Pick<
|
|
AgentInputs,
|
|
'memoryType' | 'conversationId' | 'slidingWindowSize' | 'slidingWindowTokens' | 'model'
|
|
>
|
|
|
|
function isMemoryEnabled(config: PiMemoryConfig): boolean {
|
|
return !!config.memoryType && config.memoryType !== 'none'
|
|
}
|
|
|
|
/** Resolves selected skill inputs to full `{ name, content }` entries for Pi. */
|
|
export async function resolvePiSkills(
|
|
skillInputs: unknown,
|
|
workspaceId: string | undefined
|
|
): Promise<PiSkill[]> {
|
|
if (!Array.isArray(skillInputs) || !workspaceId) return []
|
|
|
|
const skills: PiSkill[] = []
|
|
for (const input of skillInputs as SkillInput[]) {
|
|
if (!input?.skillId) continue
|
|
try {
|
|
const resolved = await resolveSkillContentById(input.skillId, workspaceId)
|
|
if (resolved) skills.push({ name: resolved.name, content: resolved.content })
|
|
} catch (error) {
|
|
logger.warn('Failed to resolve skill for Pi', {
|
|
skillId: input.skillId,
|
|
error: getErrorMessage(error),
|
|
})
|
|
}
|
|
}
|
|
return skills
|
|
}
|
|
|
|
/** Loads prior conversation messages to seed the Pi run. */
|
|
export async function loadPiMemory(
|
|
ctx: ExecutionContext,
|
|
config: PiMemoryConfig
|
|
): Promise<PiMessage[]> {
|
|
if (!isMemoryEnabled(config)) return []
|
|
try {
|
|
const messages = await memoryService.fetchMemoryMessages(ctx, config)
|
|
return messages.map((message: Message) => ({ role: message.role, content: message.content }))
|
|
} catch (error) {
|
|
logger.warn('Failed to load Pi memory', { error: getErrorMessage(error) })
|
|
return []
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Builds the prompt: optional operating `guidance` (mode-specific constraints),
|
|
* then skills, prior memory, and the task.
|
|
*/
|
|
export function buildPiPrompt(input: {
|
|
skills: PiSkill[]
|
|
initialMessages: PiMessage[]
|
|
task: string
|
|
guidance?: string
|
|
}): string {
|
|
const parts: string[] = []
|
|
|
|
if (input.guidance) {
|
|
parts.push(`# Operating instructions\n${input.guidance}`)
|
|
}
|
|
|
|
if (input.skills.length > 0) {
|
|
parts.push('# Available skills')
|
|
for (const skill of input.skills) {
|
|
parts.push(`## ${skill.name}\n${skill.content}`)
|
|
}
|
|
}
|
|
|
|
if (input.initialMessages.length > 0) {
|
|
parts.push('# Prior conversation')
|
|
for (const message of input.initialMessages) {
|
|
parts.push(`${message.role}: ${message.content}`)
|
|
}
|
|
}
|
|
|
|
parts.push('# Task')
|
|
parts.push(input.task)
|
|
return parts.join('\n\n')
|
|
}
|
|
|
|
/** Persists the user task and the agent's final message to memory. */
|
|
export async function appendPiMemory(
|
|
ctx: ExecutionContext,
|
|
config: PiMemoryConfig,
|
|
task: string,
|
|
finalText: string
|
|
): Promise<void> {
|
|
if (!isMemoryEnabled(config)) return
|
|
try {
|
|
await memoryService.appendToMemory(ctx, config, { role: 'user', content: task })
|
|
if (finalText) {
|
|
await memoryService.appendToMemory(ctx, config, { role: 'assistant', content: finalText })
|
|
}
|
|
} catch (error) {
|
|
logger.warn('Failed to append Pi memory', { error: getErrorMessage(error) })
|
|
}
|
|
}
|