Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 13:20:55 +08:00

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) })
}
}