@granular-software/sdk 0.4.18 → 0.4.20

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agent-harness.ts"],"names":[],"mappings":"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","file":"agent-harness.mjs","sourcesContent":["export interface HarnessPromptLike {\n id: string;\n type?: string;\n title?: string;\n message?: string;\n}\n\nexport interface HarnessControllerBudgets {\n maxIterations?: number;\n maxNoProgressIterations?: number;\n}\n\nexport interface HarnessVerifierSnapshotInput {\n finalCode?: string;\n resultPreview?: string;\n liveDoc: Record<string, unknown> | null;\n projectionOptions?: HarnessProjectionOptions;\n}\n\nexport interface HarnessVerifierSnapshot {\n codeDigest: string | null;\n resultDigest: string | null;\n heapDigest: string;\n loopDigest: string;\n}\n\nexport interface HarnessContinuationDecision {\n shouldContinue: boolean;\n outcome: \"continue\" | \"await_user\" | \"done\" | \"stalled\" | \"budget_exhausted\";\n reason:\n | \"workflow_closed\"\n | \"open_prompt\"\n | \"user_reply_complete\"\n | \"iteration_budget_exhausted\"\n | \"stalled_no_progress\"\n | \"progress_detected\"\n | \"no_prior_snapshot\";\n nextNoProgressCount: number;\n}\n\nexport interface GranularAgentSessionContext {\n sandboxId?: string | null;\n environmentId?: string | null;\n userId?: string | null;\n granularId?: string | null;\n userName?: string | null;\n domainRevision?: string | null;\n}\n\nexport interface GranularAgentToolInfo {\n name: string;\n description?: string;\n className?: string;\n static?: boolean;\n ready?: boolean;\n}\n\nexport interface GranularAgentExecutionCheckpoint {\n iteration?: number;\n latestJobStatus?: string | null;\n latestJobResult?: string | null;\n latestJobError?: string | null;\n latestActionSummary?: string[] | null;\n controllerOutcome?: string | null;\n controllerReason?: string | null;\n noProgressCount?: number;\n}\n\nexport interface GranularAgentWorkflowFocus {\n boundaryTimestamp: number;\n boundaryReason: \"session_start\" | \"last_closed_loop\" | \"request_start\";\n latestClosureId?: string | null;\n activeTaskIds: string[];\n openDecisionIds: string[];\n openPromptIds: string[];\n variableNames: string[];\n listNames: string[];\n entryPaths: string[];\n recentActionSummary: string[];\n}\n\nexport interface GranularAgentHeapSummaryOptions {\n focus?: Partial<Pick<GranularAgentWorkflowFocus, \"variableNames\" | \"listNames\" | \"entryPaths\">> | null;\n maxVariables?: number;\n maxLists?: number;\n maxEntries?: number;\n}\n\nexport interface HarnessProjectionOptions {\n boundaryTimestamp?: number | null;\n}\n\nexport interface BuildGranularAgentSystemPromptInput {\n domainDocumentation?: string;\n sessionContext?: GranularAgentSessionContext;\n heapSummary?: string;\n loopSummary?: string;\n workflowSummary?: string;\n tools?: GranularAgentToolInfo[];\n checkpoint?: GranularAgentExecutionCheckpoint | null;\n}\n\nexport interface GeneratedJobCodeIssue {\n code:\n | \"commonjs_require\"\n | \"placeholder_after_confirm\"\n | \"placeholder_after_ask_user\"\n | \"disambiguation_requires_choice\"\n | \"missing_user_reply\";\n severity: \"error\";\n message: string;\n}\n\ntype HeapFieldValue = string | number | boolean | null;\n\ninterface HeapFieldLike {\n name?: string;\n value?: HeapFieldValue;\n}\n\ninterface HeapEntryLike {\n path?: string;\n className?: string;\n id?: string;\n label?: string | null;\n fields?: HeapFieldLike[];\n updatedAt?: number;\n}\n\ninterface HeapListLike {\n name?: string;\n className?: string;\n paths?: string[];\n updatedAt?: number;\n}\n\ninterface HeapVariableLike {\n name?: string;\n kind?: \"entry\" | \"list\" | \"scalar\";\n entryPath?: string;\n listName?: string;\n className?: string;\n value?: HeapFieldValue;\n updatedAt?: number;\n}\n\ninterface ClosureLike {\n closureId?: string;\n status?: string;\n summary?: string;\n createdAt?: number;\n}\n\ninterface JobLike {\n jobId?: string;\n status?: string;\n submittedAt?: number;\n startedAt?: number;\n finishedAt?: number;\n actionSummary?: string[];\n actionTrace?: Array<Record<string, unknown>>;\n prompts?: Record<string, unknown>;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return null;\n return value as Record<string, unknown>;\n}\n\nfunction asArray<T = unknown>(value: unknown): T[] {\n return Array.isArray(value) ? value as T[] : [];\n}\n\nfunction toSortedRecords(value: unknown): Array<Record<string, unknown>> {\n return Object.values(asRecord(value) || {})\n .map((entry) => asRecord(entry))\n .filter((entry): entry is Record<string, unknown> => Boolean(entry));\n}\n\nfunction uniqueStrings(values: Array<string | null | undefined>, maxCount?: number): string[] {\n const seen = new Set<string>();\n const output: string[] = [];\n for (const value of values) {\n if (typeof value !== \"string\") continue;\n const normalized = value.trim();\n if (!normalized || seen.has(normalized)) continue;\n seen.add(normalized);\n output.push(normalized);\n if (typeof maxCount === \"number\" && output.length >= maxCount) break;\n }\n return output;\n}\n\nfunction formatScalar(value: HeapFieldValue | undefined): string {\n if (typeof value === \"string\") return JSON.stringify(value);\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n if (value === null) return \"null\";\n return \"unknown\";\n}\n\nfunction describeHeapEntry(entry: HeapEntryLike, previewFieldLimit = 3): string {\n const headline = entry.label || entry.id || entry.path || \"Unknown\";\n const pathLabel = entry.path && entry.path !== headline ? ` <${entry.path}>` : \"\";\n const classLabel = entry.className || \"unknown\";\n const preview = asArray<HeapFieldLike>(entry.fields)\n .filter((field) => field?.name && field.name !== \"_realId\" && field.name !== \"real_id\")\n .slice(0, previewFieldLimit)\n .map((field) => `${field.name}=${formatScalar(field.value)}`)\n .join(\", \");\n return preview\n ? `${headline}${pathLabel} [${classLabel}] ${preview}`\n : `${headline}${pathLabel} [${classLabel}]`;\n}\n\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== \"object\") {\n return JSON.stringify(value);\n }\n if (Array.isArray(value)) {\n return `[${value.map((entry) => stableStringify(entry)).join(\",\")}]`;\n }\n const record = value as Record<string, unknown>;\n return `{${Object.keys(record)\n .sort()\n .map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`)\n .join(\",\")}}`;\n}\n\nfunction hashString(value: string | null | undefined): string | null {\n if (!value) return null;\n let hash = 0x811c9dc5;\n for (let index = 0; index < value.length; index += 1) {\n hash ^= value.charCodeAt(index);\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n\nfunction hasSubstantiveAwaitAfterPrompt(code: string, marker: string): boolean {\n const startIndex = code.indexOf(marker);\n if (startIndex === -1) return true;\n const segment = code.slice(startIndex + marker.length);\n const callMatches = segment.matchAll(/await\\s+([A-Za-z0-9_$.]+)\\.([A-Za-z0-9_]+)\\s*\\(/g);\n for (const match of callMatches) {\n const receiver = match[1] || \"\";\n const method = match[2] || \"\";\n if (receiver === \"loop\" || receiver === \"heap\") continue;\n if (method.startsWith(\"get_\") || method.startsWith(\"get\")) continue;\n return true;\n }\n return false;\n}\n\nexport function reviewGeneratedJobCode(code: string): GeneratedJobCodeIssue[] {\n const normalized = typeof code === \"string\" ? code : \"\";\n if (!normalized.trim()) return [];\n\n const issues: GeneratedJobCodeIssue[] = [];\n if (/require\\s*\\(\\s*['\"]\\.\\/sandbox-tools['\"]\\s*\\)/.test(normalized)) {\n issues.push({\n code: \"commonjs_require\",\n severity: \"error\",\n message:\n \"Use ESM imports like `import { Customer, loop } from './sandbox-tools';` instead of require('./sandbox-tools'). Generated jobs must be plain runnable JavaScript for the sandbox runtime.\",\n });\n }\n const placeholderPatterns = [\n /ready to make the change next/i,\n /ready to .* next/i,\n /ready to .* now/i,\n /i can make the change now/i,\n /i can do that next/i,\n /i'?m ready to continue/i,\n /have your approval .* ready to make/i,\n /approved\\./i,\n ];\n\n if (normalized.includes(\"await loop.confirm(\")) {\n const postConfirm = normalized.slice(normalized.indexOf(\"await loop.confirm(\"));\n const hasPlaceholder = placeholderPatterns.some((pattern) => pattern.test(postConfirm));\n const hasSubstantiveAwait = hasSubstantiveAwaitAfterPrompt(normalized, \"await loop.confirm(\");\n if (!hasSubstantiveAwait || hasPlaceholder) {\n issues.push({\n code: \"placeholder_after_confirm\",\n severity: \"error\",\n message:\n \"After await loop.confirm(...) returns true, the job must perform the approved mutation in the same resumed run. Do not stop with placeholder text like 'Approved, I can make the change now.'\",\n });\n }\n }\n\n if (normalized.includes(\"await loop.ask_user(\")) {\n const postPrompt = normalized.slice(normalized.indexOf(\"await loop.ask_user(\"));\n const hasPlaceholder = placeholderPatterns.some((pattern) => pattern.test(postPrompt));\n const hasSubstantiveAwait = hasSubstantiveAwaitAfterPrompt(normalized, \"await loop.ask_user(\");\n if (hasPlaceholder && !hasSubstantiveAwait) {\n issues.push({\n code: \"placeholder_after_ask_user\",\n severity: \"error\",\n message:\n \"After await loop.ask_user(...) returns a usable answer, continue the workflow in the same resumed run instead of stopping with placeholder text about doing the work later.\",\n });\n }\n\n const askUserCalls = normalized.match(/await\\s+loop\\.ask_user\\s*\\(\\s*\\{[\\s\\S]*?\\}\\s*\\)/g) || [];\n for (const call of askUserCalls) {\n const usesChoiceType = /type\\s*:\\s*['\"]choice['\"]/.test(call);\n const usesInputType = /type\\s*:\\s*['\"]input['\"]/.test(call);\n const hasDisambiguationLanguage = /(which|choose|pick|select)/i.test(call)\n && /(invoice|order|shipment|request|case|work[\\s_-]?order)/i.test(call);\n const includesShortlistOptions = /options\\s*:\\s*\\[/.test(call);\n if (!usesChoiceType && (usesInputType || hasDisambiguationLanguage || includesShortlistOptions)) {\n issues.push({\n code: \"disambiguation_requires_choice\",\n severity: \"error\",\n message:\n \"When asking the user to choose between known concrete records such as invoices, orders, shipments, requests, cases, or work orders, use loop.ask_user({ type: 'choice', options: [...] }) with a short explicit shortlist instead of a free-text input.\",\n });\n break;\n }\n }\n }\n\n const hasConversationalReturn = /return\\s+[`'\"]/.test(normalized)\n || /\\breply\\s*:/.test(normalized)\n || /\\bagent_message\\s*\\(/.test(normalized);\n const returnsObjectLiteral = /return\\s+\\{[\\s\\S]*?\\}/.test(normalized);\n const closesLoop = /loop\\.close_loop\\s*\\(/.test(normalized);\n if (!hasConversationalReturn && returnsObjectLiteral && !closesLoop) {\n issues.push({\n code: \"missing_user_reply\",\n severity: \"error\",\n message:\n \"User-facing jobs must end with a natural-language answer. Return a short string, an object with a top-level `reply` string, or use agent_message({ reply, show }). Do not end with bare structured JSON.\",\n });\n }\n\n return issues;\n}\n\nfunction extractFocusHintsFromActionSummary(actionSummaryLines: string[]): {\n variableNames: string[];\n listNames: string[];\n entryPaths: string[];\n} {\n const variableNames: string[] = [];\n const listNames: string[] = [];\n const entryPaths: string[] = [];\n\n for (const line of actionSummaryLines) {\n const variableMatch = line.match(/\\bname=\"([^\"]+)\"/);\n if (variableMatch?.[1]) {\n variableNames.push(variableMatch[1]);\n }\n const listMatch = line.match(/\\bsaveAs=\"([^\"]+)\"/);\n if (listMatch?.[1]) {\n listNames.push(listMatch[1]);\n }\n const pathMatch = line.match(/\\bpath=\"([^\"]+)\"/);\n if (pathMatch?.[1]) {\n entryPaths.push(pathMatch[1]);\n }\n }\n\n return {\n variableNames: uniqueStrings(variableNames, 6),\n listNames: uniqueStrings(listNames, 6),\n entryPaths: uniqueStrings(entryPaths, 8),\n };\n}\n\nexport function getCurrentClosureId(liveDoc: Record<string, unknown> | null): string | null {\n const loop = asRecord(liveDoc?.loop);\n return typeof loop?.currentClosureId === \"string\" ? loop.currentClosureId : null;\n}\n\nfunction getLatestClosure(liveDoc: Record<string, unknown> | null): ClosureLike | null {\n const loop = asRecord(liveDoc?.loop);\n const currentClosureId = getCurrentClosureId(liveDoc);\n const closuresById = asRecord(loop?.closuresById) || {};\n const currentClosure = currentClosureId\n ? asRecord(closuresById[currentClosureId]) as ClosureLike | null\n : null;\n if (currentClosure) {\n return {\n ...currentClosure,\n closureId: currentClosureId || undefined,\n };\n }\n\n const closures: ClosureLike[] = [];\n for (const [closureId, value] of Object.entries(closuresById)) {\n const record = asRecord(value) as ClosureLike | null;\n if (!record) continue;\n closures.push({ ...record, closureId });\n }\n closures.sort((left, right) => (Number(right.createdAt) || 0) - (Number(left.createdAt) || 0));\n\n return closures[0] || null;\n}\n\nfunction getWorkflowBoundary(\n liveDoc: Record<string, unknown> | null,\n options?: HarnessProjectionOptions,\n): {\n timestamp: number;\n reason: \"session_start\" | \"last_closed_loop\" | \"request_start\";\n latestClosureId: string | null;\n} {\n const latestClosure = getLatestClosure(liveDoc);\n const explicitBoundaryTimestamp = typeof options?.boundaryTimestamp === \"number\"\n ? options.boundaryTimestamp\n : null;\n const latestClosureTimestamp = Number(latestClosure?.createdAt) || 0;\n\n if (explicitBoundaryTimestamp !== null && explicitBoundaryTimestamp > latestClosureTimestamp) {\n return {\n timestamp: explicitBoundaryTimestamp,\n reason: \"request_start\",\n latestClosureId: null,\n };\n }\n\n if (!latestClosure) {\n return {\n timestamp: explicitBoundaryTimestamp ?? 0,\n reason: explicitBoundaryTimestamp !== null && explicitBoundaryTimestamp > 0\n ? \"request_start\"\n : \"session_start\",\n latestClosureId: null,\n };\n }\n\n return {\n timestamp: Number(latestClosure.createdAt) || 0,\n reason: \"last_closed_loop\",\n latestClosureId: typeof latestClosure.closureId === \"string\" ? latestClosure.closureId : null,\n };\n}\n\nfunction getJobTimestamp(job: Record<string, unknown>): number {\n return Number(job.finishedAt) || Number(job.startedAt) || Number(job.submittedAt) || 0;\n}\n\nfunction getJobRecords(liveDoc: Record<string, unknown> | null): JobLike[] {\n const jobsById = asRecord(asRecord(liveDoc?.jobs)?.byId) || {};\n const jobs: JobLike[] = [];\n for (const [jobId, value] of Object.entries(jobsById)) {\n const record = asRecord(value) as JobLike | null;\n if (!record) continue;\n jobs.push({ ...record, jobId });\n }\n jobs.sort((left, right) => getJobTimestamp(right as unknown as Record<string, unknown>) - getJobTimestamp(left as unknown as Record<string, unknown>));\n return jobs;\n}\n\nfunction getPromptRecordsFromJobs(\n liveDoc: Record<string, unknown> | null,\n): Array<Record<string, unknown>> {\n return getJobRecords(liveDoc)\n .flatMap((job) => Object.values(asRecord(job.prompts) || {}))\n .map((prompt) => asRecord(prompt))\n .filter((prompt): prompt is Record<string, unknown> => Boolean(prompt));\n}\n\nexport function projectWorkflowFocus(\n liveDoc: Record<string, unknown> | null,\n pendingPrompts: HarnessPromptLike[] = [],\n options?: HarnessProjectionOptions,\n): GranularAgentWorkflowFocus {\n const boundary = getWorkflowBoundary(liveDoc, options);\n const jobs = getJobRecords(liveDoc)\n .filter((job) => getJobTimestamp(job as unknown as Record<string, unknown>) >= boundary.timestamp)\n .slice(0, 6)\n .reverse();\n\n const actionSummaryLines: string[] = [];\n const variableNames: string[] = [];\n const listNames: string[] = [];\n const entryPaths: string[] = [];\n const activeTaskIds: string[] = [];\n const openDecisionIds: string[] = [];\n const openPromptIds: string[] = [];\n\n for (const job of jobs) {\n for (const line of asArray<string>(job.actionSummary)) {\n if (typeof line === \"string\" && line.trim()) {\n actionSummaryLines.push(line.trim());\n }\n }\n\n for (const rawEvent of asArray<Record<string, unknown>>(job.actionTrace)) {\n const event = asRecord(rawEvent);\n const details = asRecord(event?.details);\n const outcome = asRecord(event?.outcome);\n\n if (typeof details?.name === \"string\") {\n variableNames.push(details.name);\n }\n if (typeof details?.saveAs === \"string\") {\n listNames.push(details.saveAs);\n }\n if (typeof details?.path === \"string\") {\n entryPaths.push(details.path);\n }\n if (typeof details?.taskId === \"string\") {\n activeTaskIds.push(details.taskId);\n }\n if (typeof details?.decisionId === \"string\") {\n openDecisionIds.push(details.decisionId);\n }\n\n if (typeof outcome?.taskId === \"string\") {\n activeTaskIds.push(outcome.taskId);\n }\n if (typeof outcome?.decisionId === \"string\") {\n openDecisionIds.push(outcome.decisionId);\n }\n if (typeof outcome?.promptId === \"string\") {\n openPromptIds.push(outcome.promptId);\n }\n }\n }\n\n const loop = asRecord(liveDoc?.loop);\n const tasks = toSortedRecords(loop?.tasksById)\n .filter((task) => {\n const updatedAt = Number(task.updatedAt) || Number(task.createdAt) || 0;\n const status = typeof task.status === \"string\" ? task.status : \"pending\";\n if (boundary.reason === \"request_start\") {\n return updatedAt >= boundary.timestamp;\n }\n return status !== \"completed\" && status !== \"canceled\"\n ? true\n : updatedAt >= boundary.timestamp;\n })\n .sort((left, right) => (Number(right.updatedAt) || Number(right.createdAt) || 0) - (Number(left.updatedAt) || Number(left.createdAt) || 0));\n for (const task of tasks.slice(0, 4)) {\n if (typeof task.taskId === \"string\") {\n activeTaskIds.push(task.taskId);\n }\n }\n\n const decisions = toSortedRecords(loop?.decisionsById)\n .filter((decision) => {\n const updatedAt = Number(decision.updatedAt) || Number(decision.createdAt) || 0;\n if (boundary.reason === \"request_start\") {\n return updatedAt >= boundary.timestamp;\n }\n return decision.status === \"open\" || updatedAt >= boundary.timestamp;\n })\n .sort((left, right) => (Number(right.updatedAt) || Number(right.createdAt) || 0) - (Number(left.updatedAt) || Number(left.createdAt) || 0));\n for (const decision of decisions.slice(0, 3)) {\n if (typeof decision.decisionId === \"string\" && decision.status === \"open\") {\n openDecisionIds.push(decision.decisionId);\n }\n }\n\n const promptRecords = getPromptRecordsFromJobs(liveDoc)\n .filter((prompt) => {\n const openedAt = Number(prompt.openedAt) || 0;\n if (boundary.reason === \"request_start\") {\n return openedAt >= boundary.timestamp;\n }\n return prompt.status === \"open\" || openedAt >= boundary.timestamp;\n });\n for (const prompt of promptRecords) {\n const promptId = typeof prompt.promptId === \"string\"\n ? prompt.promptId\n : typeof prompt.id === \"string\"\n ? prompt.id\n : null;\n if (promptId && prompt.status === \"open\") {\n openPromptIds.push(promptId);\n }\n }\n for (const prompt of pendingPrompts) {\n if (typeof prompt.id === \"string\") {\n openPromptIds.push(prompt.id);\n }\n }\n\n const heap = asRecord(liveDoc?.heap);\n const variablesByName = asRecord(heap?.variablesByName) || {};\n const listsByName = asRecord(heap?.listsByName) || {};\n const recentHints = extractFocusHintsFromActionSummary(actionSummaryLines);\n\n variableNames.push(...recentHints.variableNames);\n listNames.push(...recentHints.listNames);\n entryPaths.push(...recentHints.entryPaths);\n\n for (const variableName of uniqueStrings(variableNames)) {\n const variable = asRecord(variablesByName[variableName]);\n if (!variable) continue;\n if (typeof variable.listName === \"string\") {\n listNames.push(variable.listName);\n }\n if (typeof variable.entryPath === \"string\") {\n entryPaths.push(variable.entryPath);\n }\n }\n for (const listName of uniqueStrings(listNames)) {\n const list = asRecord(listsByName[listName]);\n for (const path of asArray<string>(list?.paths).slice(0, 4)) {\n entryPaths.push(path);\n }\n }\n\n if (variableNames.length === 0 && boundary.reason !== \"request_start\") {\n const recentVariables = Object.values(variablesByName)\n .map((value) => asRecord(value) as HeapVariableLike | null)\n .filter((value): value is HeapVariableLike => Boolean(value))\n .sort((left, right) => (right.updatedAt || 0) - (left.updatedAt || 0))\n .slice(0, 3);\n for (const variable of recentVariables) {\n if (typeof variable.name === \"string\") {\n variableNames.push(variable.name);\n }\n if (typeof variable.listName === \"string\") {\n listNames.push(variable.listName);\n }\n if (typeof variable.entryPath === \"string\") {\n entryPaths.push(variable.entryPath);\n }\n }\n }\n\n return {\n boundaryTimestamp: boundary.timestamp,\n boundaryReason: boundary.reason,\n latestClosureId: boundary.latestClosureId,\n activeTaskIds: uniqueStrings(activeTaskIds, 4),\n openDecisionIds: uniqueStrings(openDecisionIds, 3),\n openPromptIds: uniqueStrings(openPromptIds, 3),\n variableNames: uniqueStrings(variableNames, 4),\n listNames: uniqueStrings(listNames, 4),\n entryPaths: uniqueStrings(entryPaths, 6),\n recentActionSummary: uniqueStrings(actionSummaryLines, 8),\n };\n}\n\nexport function projectWorkflowSummary(\n liveDoc: Record<string, unknown> | null,\n pendingPrompts: HarnessPromptLike[] = [],\n options?: HarnessProjectionOptions,\n): string {\n const focus = projectWorkflowFocus(liveDoc, pendingPrompts, options);\n const lines: string[] = [];\n lines.push(\"Workflow Boundary:\");\n if (focus.boundaryReason === \"request_start\") {\n lines.push(\"- Start from work recorded after the current user request began.\");\n } else if (focus.boundaryReason === \"last_closed_loop\" && focus.latestClosureId) {\n lines.push(`- Start from work recorded after ${focus.latestClosureId}.`);\n } else {\n lines.push(\"- No prior closed loop recorded; use the latest user request as the boundary.\");\n }\n\n lines.push(\"\", \"Recent Actions:\");\n if (focus.recentActionSummary.length === 0) {\n lines.push(\"- none\");\n } else {\n for (const line of focus.recentActionSummary) {\n lines.push(line.startsWith(\"- \") ? line : `- ${line}`);\n }\n }\n\n lines.push(\"\", \"Working Set Hints:\");\n if (focus.variableNames.length === 0 && focus.listNames.length === 0 && focus.entryPaths.length === 0) {\n lines.push(\"- none\");\n } else {\n if (focus.variableNames.length > 0) {\n lines.push(`- variables: ${focus.variableNames.join(\", \")}`);\n }\n if (focus.listNames.length > 0) {\n lines.push(`- lists: ${focus.listNames.join(\", \")}`);\n }\n if (focus.entryPaths.length > 0) {\n lines.push(`- entries: ${focus.entryPaths.join(\", \")}`);\n }\n }\n\n lines.push(\"\", \"Open Workflow Handles:\");\n if (focus.activeTaskIds.length === 0 && focus.openDecisionIds.length === 0 && focus.openPromptIds.length === 0) {\n lines.push(\"- none\");\n } else {\n if (focus.activeTaskIds.length > 0) {\n lines.push(`- tasks: ${focus.activeTaskIds.join(\", \")}`);\n }\n if (focus.openDecisionIds.length > 0) {\n lines.push(`- decisions: ${focus.openDecisionIds.join(\", \")}`);\n }\n if (focus.openPromptIds.length > 0) {\n lines.push(`- prompts: ${focus.openPromptIds.join(\", \")}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function hasOpenPrompt(\n liveDoc: Record<string, unknown> | null,\n pendingPrompts: HarnessPromptLike[],\n): boolean {\n if (pendingPrompts.length > 0) return true;\n const jobsById = asRecord(asRecord(liveDoc?.jobs)?.byId) || {};\n for (const job of Object.values(jobsById)) {\n const prompts = asRecord(asRecord(job)?.prompts);\n if (!prompts) continue;\n for (const prompt of Object.values(prompts)) {\n const record = asRecord(prompt);\n if (record?.status === \"open\") return true;\n }\n }\n return false;\n}\n\nexport function getExclusivePromptTarget<T extends HarnessPromptLike>(pendingPrompts: T[]): T | null {\n if (pendingPrompts.length !== 1) return null;\n const [prompt] = pendingPrompts;\n return prompt?.type === \"input\" ? prompt : null;\n}\n\nexport function projectLoopSummary(\n liveDoc: Record<string, unknown> | null,\n pendingPrompts: HarnessPromptLike[] = [],\n options?: HarnessProjectionOptions,\n): string {\n const lines: string[] = [];\n const loop = asRecord(liveDoc?.loop);\n const boundary = getWorkflowBoundary(liveDoc, options);\n const tasks = toSortedRecords(loop?.tasksById)\n .filter((task) => {\n const updatedAt = Number(task.updatedAt) || Number(task.createdAt) || 0;\n const status = typeof task.status === \"string\" ? task.status : \"pending\";\n if (boundary.reason === \"request_start\") {\n return updatedAt >= boundary.timestamp;\n }\n return status !== \"completed\" && status !== \"canceled\"\n ? true\n : updatedAt >= boundary.timestamp;\n })\n .sort((left, right) => (Number(right.updatedAt) || 0) - (Number(left.updatedAt) || 0));\n const activeTasks = tasks.filter((task) => {\n const status = typeof task.status === \"string\" ? task.status : \"pending\";\n return status !== \"completed\" && status !== \"canceled\";\n });\n const visibleTasks = (activeTasks.length > 0 ? activeTasks : tasks).slice(0, 5);\n const hiddenTaskCount = Math.max(0, activeTasks.length - visibleTasks.length);\n\n lines.push(\"Tasks:\");\n if (visibleTasks.length === 0) {\n lines.push(\"- none\");\n } else {\n lines.push(\"- Reuse existing taskId values exactly as written below.\");\n for (const task of visibleTasks) {\n const title = typeof task.title === \"string\" ? task.title : \"Untitled task\";\n const taskId = typeof task.taskId === \"string\" ? task.taskId : \"unknown\";\n const status = typeof task.status === \"string\" ? task.status : \"pending\";\n const summary = typeof task.summary === \"string\" && task.summary.trim()\n ? ` — ${task.summary.trim()}`\n : \"\";\n lines.push(`- [${status}] ${title} (${taskId})${summary}`);\n }\n if (hiddenTaskCount > 0) {\n lines.push(`- ${hiddenTaskCount} more active task(s) omitted`);\n }\n }\n\n const decisions = toSortedRecords(loop?.decisionsById)\n .filter((decision) => {\n const updatedAt = Number(decision.updatedAt) || Number(decision.createdAt) || 0;\n if (boundary.reason === \"request_start\") {\n return updatedAt >= boundary.timestamp;\n }\n return decision.status === \"open\" || updatedAt >= boundary.timestamp;\n })\n .sort((left, right) => (Number(right.updatedAt) || Number(right.createdAt) || 0) - (Number(left.updatedAt) || Number(left.createdAt) || 0));\n const openDecisions = decisions.filter((decision) => decision.status === \"open\");\n const visibleDecisions = (openDecisions.length > 0 ? openDecisions : decisions.slice(0, 1)).slice(0, 3);\n\n lines.push(\"\", \"Recent Decisions:\");\n if (visibleDecisions.length === 0) {\n lines.push(\"- none\");\n } else {\n lines.push(\"- Reuse existing decisionId values exactly as written below.\");\n for (const decision of visibleDecisions) {\n const status = typeof decision.status === \"string\" ? decision.status : \"resolved\";\n const title = typeof decision.title === \"string\" && decision.title.trim()\n ? decision.title.trim()\n : \"Decision\";\n const decisionId = typeof decision.decisionId === \"string\" ? decision.decisionId : \"unknown\";\n if (status === \"open\") {\n const candidatePreview = asArray(decision.candidates)\n .slice(0, 3)\n .map((candidate) => {\n const record = asRecord(candidate);\n if (!record) return null;\n const candidateId = typeof record.id === \"string\" ? record.id : \"unknown\";\n const candidateLabel = typeof record.label === \"string\" && record.label.trim()\n ? record.label.trim()\n : candidateId;\n return candidateLabel === candidateId ? candidateId : `${candidateLabel} (${candidateId})`;\n })\n .filter((value): value is string => Boolean(value))\n .join(\", \");\n lines.push(`- [open] ${title} (${decisionId})${candidatePreview ? ` — candidates: ${candidatePreview}` : \"\"}`);\n } else {\n const selected = asRecord(decision.selected);\n const label = typeof selected?.label === \"string\"\n ? selected.label\n : typeof selected?.id === \"string\"\n ? selected.id\n : \"unknown\";\n lines.push(`- [resolved] ${title} (${decisionId}) -> ${label}`);\n }\n }\n }\n\n const openPrompts = [\n ...pendingPrompts.map((prompt) => ({\n id: prompt.id,\n type: prompt.type,\n title: prompt.title,\n message: prompt.message,\n })),\n ...Object.values(asRecord(asRecord(liveDoc?.jobs)?.byId) || {})\n .flatMap((job) => Object.values(asRecord(asRecord(job)?.prompts) || {}))\n .map((prompt) => asRecord(prompt))\n .filter((prompt): prompt is Record<string, unknown> => Boolean(prompt && prompt.status === \"open\")),\n ];\n const visiblePrompts = boundary.reason === \"request_start\"\n ? openPrompts.filter((prompt) => {\n const promptRecord = asRecord(prompt);\n const openedAt = Number(promptRecord?.openedAt) || 0;\n const promptId = typeof promptRecord?.id === \"string\"\n ? promptRecord.id\n : typeof prompt.id === \"string\"\n ? prompt.id\n : null;\n return openedAt >= boundary.timestamp || (promptId\n ? pendingPrompts.some((pendingPrompt) => pendingPrompt.id === promptId)\n : false);\n })\n : openPrompts;\n\n lines.push(\"\", \"Open Prompts:\");\n if (visiblePrompts.length === 0) {\n lines.push(\"- none\");\n } else {\n for (const prompt of visiblePrompts.slice(0, 3)) {\n const title = typeof prompt.title === \"string\" && prompt.title.trim() ? prompt.title.trim() : \"Input required\";\n const type = typeof prompt.type === \"string\" ? prompt.type : \"input\";\n const message = typeof prompt.message === \"string\" && prompt.message.trim()\n ? ` — ${prompt.message.trim()}`\n : \"\";\n lines.push(`- [${type}] ${title}${message}`);\n }\n }\n\n const currentClosureId = getCurrentClosureId(liveDoc);\n const closureRecord = currentClosureId\n ? asRecord(asRecord(loop?.closuresById)?.[currentClosureId])\n : null;\n const visibleClosure = closureRecord && (\n boundary.reason !== \"request_start\"\n || (Number(closureRecord.createdAt) || 0) >= boundary.timestamp\n )\n ? closureRecord\n : null;\n lines.push(\"\", \"Loop Closure:\");\n if (visibleClosure) {\n const status = typeof visibleClosure.status === \"string\" ? visibleClosure.status : \"completed\";\n const summary = typeof visibleClosure.summary === \"string\" ? visibleClosure.summary : \"No summary\";\n lines.push(`- current: [${status}] ${summary} (${currentClosureId})`);\n } else {\n lines.push(\"- none\");\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function projectHeapSummary(heap: unknown, options?: GranularAgentHeapSummaryOptions): string {\n const heapRecord = asRecord(heap) || {};\n const entriesByPath = asRecord(heapRecord.entriesByPath) || {};\n const listsByName = asRecord(heapRecord.listsByName) || {};\n const variablesByName = asRecord(heapRecord.variablesByName) || {};\n const focusedVariableNames = new Set(uniqueStrings(options?.focus?.variableNames || []));\n const focusedListNames = new Set(uniqueStrings(options?.focus?.listNames || []));\n const focusedEntryPaths = new Set(uniqueStrings(options?.focus?.entryPaths || []));\n const hasFocus = focusedVariableNames.size > 0 || focusedListNames.size > 0 || focusedEntryPaths.size > 0;\n const suppressRecentFallback = Boolean(options?.focus) && !hasFocus;\n const maxVariables = options?.maxVariables ?? (hasFocus ? 4 : 6);\n const maxLists = options?.maxLists ?? (hasFocus ? 3 : 4);\n const maxEntries = options?.maxEntries ?? (hasFocus ? 5 : 6);\n\n const variables = suppressRecentFallback\n ? []\n : Object.values(variablesByName)\n .map((value) => asRecord(value) as HeapVariableLike | null)\n .filter((value): value is HeapVariableLike => Boolean(value))\n .sort((left, right) => {\n const leftFocused = left.name && focusedVariableNames.has(left.name) ? 1 : 0;\n const rightFocused = right.name && focusedVariableNames.has(right.name) ? 1 : 0;\n return rightFocused - leftFocused || (right.updatedAt || 0) - (left.updatedAt || 0);\n })\n .filter((variable, index) => {\n if (index < maxVariables) return true;\n return Boolean(variable.name && focusedVariableNames.has(variable.name));\n })\n .slice(0, maxVariables);\n\n const referencedPaths = new Set<string>();\n for (const variable of variables) {\n if (variable.entryPath) referencedPaths.add(variable.entryPath);\n if (variable.listName) {\n const list = asRecord(listsByName[variable.listName]) as HeapListLike | null;\n for (const path of list?.paths || []) referencedPaths.add(path);\n }\n }\n for (const path of focusedEntryPaths) {\n referencedPaths.add(path);\n }\n\n const visibleLists = Object.values(listsByName)\n .map((value) => asRecord(value) as HeapListLike | null)\n .filter((value): value is HeapListLike => Boolean(value))\n .filter((list) => (\n variables.some((variable) => variable.listName === list.name)\n || Boolean(list.name && focusedListNames.has(list.name))\n ))\n .sort((left, right) => (right.updatedAt || 0) - (left.updatedAt || 0))\n .slice(0, maxLists);\n\n const visibleEntries = Object.values(entriesByPath)\n .map((value) => asRecord(value) as HeapEntryLike | null)\n .filter((value): value is HeapEntryLike => Boolean(value))\n .filter((entry) => entry.path && referencedPaths.has(entry.path))\n .sort((left, right) => (right.updatedAt || 0) - (left.updatedAt || 0))\n .slice(0, maxEntries);\n\n const lines: string[] = [];\n\n lines.push(\"Variables:\");\n if (variables.length === 0) {\n lines.push(\"- none\");\n } else {\n for (const variable of variables) {\n if (variable.kind === \"scalar\") {\n lines.push(`- ${variable.name}: scalar = ${formatScalar(variable.value)}`);\n continue;\n }\n if (variable.kind === \"entry\") {\n const entry = variable.entryPath ? asRecord(entriesByPath[variable.entryPath]) as HeapEntryLike | null : null;\n lines.push(`- ${variable.name}: entry<${variable.className || entry?.className || \"unknown\"}> -> ${entry ? describeHeapEntry(entry) : (variable.entryPath || \"missing\")}`);\n continue;\n }\n const list = variable.listName ? asRecord(listsByName[variable.listName]) as HeapListLike | null : null;\n lines.push(`- ${variable.name}: list<${variable.className || list?.className || \"unknown\"}> -> ${(list?.paths || []).length} item(s)`);\n }\n }\n\n lines.push(\"\", \"Named Lists:\");\n if (visibleLists.length === 0) {\n lines.push(\"- none\");\n } else {\n for (const list of visibleLists) {\n lines.push(`- ${list.name}: ${list.className || \"unknown\"}[${(list.paths || []).length}]`);\n }\n }\n\n lines.push(\"\", \"Active Entries:\");\n if (visibleEntries.length === 0) {\n lines.push(\"- none\");\n } else {\n for (const entry of visibleEntries) {\n lines.push(`- ${describeHeapEntry(entry)}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function createHarnessVerifierSnapshot(\n input: HarnessVerifierSnapshotInput,\n): HarnessVerifierSnapshot {\n const workflowFocus = projectWorkflowFocus(input.liveDoc, [], input.projectionOptions);\n const heapDigest = hashString(projectHeapSummary(asRecord(input.liveDoc?.heap), {\n focus: workflowFocus,\n })) || \"00000000\";\n const loopDigest = hashString(projectWorkflowSummary(input.liveDoc, [], input.projectionOptions)) || \"00000000\";\n return {\n codeDigest: hashString(input.finalCode?.trim()),\n resultDigest: hashString(input.resultPreview?.trim()),\n heapDigest,\n loopDigest,\n };\n}\n\nexport function evaluateContinuation(input: {\n iteration: number;\n budgets?: HarnessControllerBudgets;\n baselineClosureId: string | null;\n currentClosureId: string | null;\n liveDoc: Record<string, unknown> | null;\n pendingPrompts: HarnessPromptLike[];\n projectionOptions?: HarnessProjectionOptions;\n latestResponseText?: string | null;\n previousSnapshot?: HarnessVerifierSnapshot | null;\n currentSnapshot: HarnessVerifierSnapshot;\n previousNoProgressCount?: number;\n}): HarnessContinuationDecision {\n const maxIterations = input.budgets?.maxIterations ?? 6;\n const maxNoProgressIterations = input.budgets?.maxNoProgressIterations ?? 2;\n\n if (input.currentClosureId && input.currentClosureId !== input.baselineClosureId) {\n return {\n shouldContinue: false,\n outcome: \"done\",\n reason: \"workflow_closed\",\n nextNoProgressCount: 0,\n };\n }\n\n if (hasOpenPrompt(input.liveDoc, input.pendingPrompts)) {\n return {\n shouldContinue: false,\n outcome: \"await_user\",\n reason: \"open_prompt\",\n nextNoProgressCount: 0,\n };\n }\n\n const workflowFocus = projectWorkflowFocus(\n input.liveDoc,\n input.pendingPrompts,\n input.projectionOptions,\n );\n const hasOpenWorkflowHandles =\n workflowFocus.activeTaskIds.length > 0\n || workflowFocus.openDecisionIds.length > 0\n || workflowFocus.openPromptIds.length > 0;\n\n if (!hasOpenWorkflowHandles && input.latestResponseText?.trim()) {\n return {\n shouldContinue: false,\n outcome: \"done\",\n reason: \"user_reply_complete\",\n nextNoProgressCount: 0,\n };\n }\n\n if (input.iteration + 1 >= maxIterations) {\n return {\n shouldContinue: false,\n outcome: \"budget_exhausted\",\n reason: \"iteration_budget_exhausted\",\n nextNoProgressCount: input.previousNoProgressCount ?? 0,\n };\n }\n\n if (!input.previousSnapshot) {\n return {\n shouldContinue: true,\n outcome: \"continue\",\n reason: \"no_prior_snapshot\",\n nextNoProgressCount: 0,\n };\n }\n\n const madeProgress =\n input.previousSnapshot.resultDigest !== input.currentSnapshot.resultDigest\n || input.previousSnapshot.heapDigest !== input.currentSnapshot.heapDigest\n || input.previousSnapshot.loopDigest !== input.currentSnapshot.loopDigest;\n\n const nextNoProgressCount = madeProgress\n ? 0\n : (input.previousNoProgressCount ?? 0) + 1;\n\n if (nextNoProgressCount >= maxNoProgressIterations) {\n return {\n shouldContinue: false,\n outcome: \"stalled\",\n reason: \"stalled_no_progress\",\n nextNoProgressCount,\n };\n }\n\n return {\n shouldContinue: true,\n outcome: \"continue\",\n reason: \"progress_detected\",\n nextNoProgressCount,\n };\n}\n\nexport function buildContinuationInstruction(resultPreview?: string): string {\n return [\n \"Continue the same user request using the latest structured session state.\",\n \"Take only the minimum next step that directly helps the user.\",\n \"Use the active tasks, decisions, prompts, and heap references as the source of truth instead of replaying old work.\",\n \"If the user names a concrete record that is not already in the heap, fetch it from the graph instead of replying that it is not in context.\",\n \"If this request clearly spans multiple steps and there are no active tasks yet, create 2-4 short user-visible tasks now.\",\n \"Reuse any existing taskId and decisionId values exactly as they appear in AGENT LOOP STATE.\",\n \"Use ask_user with type input for open-ended preferences or missing text. Use type choice only for a short explicit shortlist.\",\n \"Do not ask for confirmation in plain text. Use loop.confirm(...) when approval is needed.\",\n \"Await loop.ask_user(...) and loop.confirm(...). Those helpers pause the current job and resume it after the user answers.\",\n \"After a resumed ask_user or confirm call, continue the same job and perform the newly authorized action when the answer is sufficient. Do not stop with placeholder text like 'I'm ready to do it next.'\",\n \"If you ask the user a new question in this job, do not also close the loop in the same job.\",\n \"Write the smallest straightforward code for the current step. Avoid defensive fallback branches for hypothetical states that are not currently true.\",\n \"Do not repeat completed work, fetch optional extra details, or store extra heap data unless it is needed right now.\",\n \"If the workflow is now completed, canceled, or blocked, call loop.close_loop(...) before stopping.\",\n resultPreview ? `Latest job result:\\n${resultPreview}` : null,\n ].filter(Boolean).join(\"\\n\\n\");\n}\n\nexport function buildGranularAgentDomainBlock(domainDocumentation?: string): string {\n return domainDocumentation?.trim()\n || \"No domain types available. The graph may not be ready yet.\";\n}\n\nexport function buildGranularAgentSessionBlock(\n sessionContext?: GranularAgentSessionContext,\n): string {\n if (!sessionContext) return \"No session metadata available.\";\n const rows = [\n [\"sandboxId\", sessionContext.sandboxId],\n [\"environmentId\", sessionContext.environmentId],\n [\"userId\", sessionContext.userId],\n [\"granularId\", sessionContext.granularId],\n [\"userName\", sessionContext.userName],\n [\"domainRevision\", sessionContext.domainRevision],\n ];\n const activeRows = rows.filter(([, value]) => Boolean(value));\n if (activeRows.length === 0) return \"No session metadata available.\";\n return activeRows.map(([key, value]) => `${key}: ${value}`).join(\"\\n\");\n}\n\nexport function buildGranularAgentHeapBlock(heapSummary?: string): string {\n return heapSummary?.trim() || \"Heap is empty for this session.\";\n}\n\nexport function buildGranularAgentLoopBlock(loopSummary?: string): string {\n return loopSummary?.trim() || \"No active loop state recorded for this session.\";\n}\n\nexport function buildGranularAgentWorkflowBlock(workflowSummary?: string): string {\n return workflowSummary?.trim() || \"No current workflow snapshot recorded for this request yet.\";\n}\n\nexport function buildGranularAgentToolBlock(\n tools?: GranularAgentToolInfo[],\n): string {\n const normalizedTools = (tools || [])\n .filter((tool) => tool?.name)\n .slice()\n .sort((left, right) => {\n const leftScope = `${left.className || \"global\"}:${left.static ? \"static\" : \"instance\"}`;\n const rightScope = `${right.className || \"global\"}:${right.static ? \"static\" : \"instance\"}`;\n return leftScope.localeCompare(rightScope) || left.name.localeCompare(right.name);\n });\n\n if (normalizedTools.length === 0) {\n return \"No live effects are available in this session yet.\";\n }\n\n const globalTools = normalizedTools.filter((tool) => !tool.className);\n const staticTools = normalizedTools.filter((tool) => Boolean(tool.className && tool.static));\n const instanceTools = normalizedTools.filter((tool) => Boolean(tool.className && !tool.static));\n\n const lines: string[] = [\n \"Treat this block as the planning map. Use DOMAIN TYPES below for exact signatures.\",\n ];\n\n const appendGroup = (title: string, group: GranularAgentToolInfo[]) => {\n lines.push(`- ${title}:`);\n if (group.length === 0) {\n lines.push(\" none\");\n return;\n }\n for (const tool of group.slice(0, 10)) {\n const availability = tool.ready === false ? \" [not ready]\" : \"\";\n const description = tool.description?.trim()\n ? ` - ${tool.description.trim()}`\n : \"\";\n lines.push(` ${tool.name}${availability}${description}`);\n }\n if (group.length > 10) {\n lines.push(` +${group.length - 10} more`);\n }\n };\n\n appendGroup(\"Global effects\", globalTools);\n appendGroup(\"Class-level effects\", staticTools);\n appendGroup(\"Record-level effects\", instanceTools);\n\n return lines.join(\"\\n\");\n}\n\nexport function buildGranularAgentCheckpointBlock(\n checkpoint?: GranularAgentExecutionCheckpoint | null,\n): string {\n if (!checkpoint) {\n return \"No previous execution checkpoint recorded for this request yet.\";\n }\n\n const lines: string[] = [];\n if (typeof checkpoint.iteration === \"number\") {\n lines.push(`iteration: ${checkpoint.iteration}`);\n }\n if (checkpoint.latestJobStatus) {\n lines.push(`latestJobStatus: ${checkpoint.latestJobStatus}`);\n }\n if (checkpoint.controllerOutcome) {\n lines.push(`controllerOutcome: ${checkpoint.controllerOutcome}`);\n }\n if (checkpoint.controllerReason) {\n lines.push(`controllerReason: ${checkpoint.controllerReason}`);\n }\n if (typeof checkpoint.noProgressCount === \"number\") {\n lines.push(`noProgressCount: ${checkpoint.noProgressCount}`);\n }\n if (checkpoint.latestJobError?.trim()) {\n lines.push(`latestJobError: ${checkpoint.latestJobError.trim()}`);\n }\n if (Array.isArray(checkpoint.latestActionSummary) && checkpoint.latestActionSummary.length > 0) {\n lines.push(\"latestActionSummary:\");\n for (const line of checkpoint.latestActionSummary.slice(0, 8)) {\n lines.push(line.startsWith(\"- \") ? line : `- ${line}`);\n }\n }\n if (checkpoint.latestJobResult?.trim()) {\n lines.push(`latestJobResult:\\n${checkpoint.latestJobResult.trim()}`);\n }\n\n return lines.length > 0\n ? lines.join(\"\\n\")\n : \"No previous execution checkpoint recorded for this request yet.\";\n}\n\nexport function buildGranularAgentSystemPrompt(\n input: BuildGranularAgentSystemPromptInput,\n): string {\n const sessionBlock = buildGranularAgentSessionBlock(input.sessionContext);\n const toolBlock = buildGranularAgentToolBlock(input.tools);\n const domainBlock = buildGranularAgentDomainBlock(input.domainDocumentation);\n const workflowBlock = buildGranularAgentWorkflowBlock(input.workflowSummary);\n const checkpointBlock = buildGranularAgentCheckpointBlock(input.checkpoint);\n const heapBlock = buildGranularAgentHeapBlock(input.heapSummary);\n const loopBlock = buildGranularAgentLoopBlock(input.loopSummary);\n\n return `You are an AI assistant for a live Granular session.\nYou can help the user understand the domain, answer questions, or generate and execute TypeScript code.\nYour tone must be natural and human-like.\n\nCall the \\`execute_code\\` effect ONLY when the user's intent matches the domain's capabilities and requires executing code against the live session. If the user is just asking a general question or if their request doesn't match the available effects or domain types, respond with text to explain.\nWhen you call \\`execute_code\\`, additional assistant text must be either:\n- empty, or\n- a brief summary of the actions the generated code will perform.\nDo not include any other kind of commentary when calling \\`execute_code\\`.\n- If the next step needs to create or update workflow state in the live session, you must call \\`execute_code\\`. This includes \\`loop.ask_user(...)\\`, \\`loop.confirm(...)\\`, \\`loop.open_decision(...)\\`, \\`loop.close_decision(...)\\`, \\`loop.create_task(...)\\`, \\`loop.update_task(...)\\`, \\`loop.complete_task(...)\\`, and \\`loop.close_loop(...)\\`.\n- Never simulate a live prompt, confirmation, decision, task change, or loop closure in plain text. Plain-text replies are only for conversational answers that do not need to mutate session state.\n\n─── STREAMING COMMENT RULES ───\n- While you are writing code, add short single-line comments with the prefix \\`// \\` before meaningful blocks.\n- These comments should explain the intent in friendly product language, not in implementation jargon.\n- Comments are shown live as a reasoning trace, so keep them brief, concrete, and useful.\n- Do not mention method names, file paths, or internal identifiers in those comments.\n- Use only single-line \\`//\\` comments for this purpose. Do not use block comments.\n- If you are replying with text only, you may also include a few leading \\`// \\` comment lines before the final answer.\n- End text-only replies with the plain user-facing answer on normal lines, without a comment prefix.\n\n─── RESPONSE STYLE RULES ───\n- Use plain, friendly product language.\n- Never mention internal implementation details in user-facing text:\n class names, effect names, method names, function names, file paths, parameter names, or code snippets.\n- Never expose dotted identifiers such as \\`Class.method\\` in user-facing text.\n- Do not say \"sandbox\" in user-facing text unless the user is explicitly asking about the runtime environment itself.\n- If you need clarification, ask in everyday language.\n- If the missing information should pause the live workflow for later continuation, ask through \\`loop.ask_user(...)\\` in generated code rather than with a plain-text question.\n- Keep replies concise and clear.\n- This is a conversation UI, not an API console. Favor human answers over machine-shaped payloads.\n\n─── SESSION CONTEXT ───\n${sessionBlock}\n\n─── CAPABILITY SNAPSHOT ───\n${toolBlock}\n\n─── DOMAIN TYPES (TypeScript declarations from ./sandbox-tools) ───\nImport classes and effect functions from \\`./sandbox-tools\\` in generated code.\nPublished effects appear as instance or static methods on the classes below, or as top-level \\`export declare function\\` entries for global effects.\n\n${domainBlock}\n\n─── EXECUTION CHECKPOINT ───\n${checkpointBlock}\n\n─── WORKFLOW SNAPSHOT ───\n${workflowBlock}\n\n─── SESSION HEAP ───\n${heapBlock}\n\n─── AGENT LOOP STATE ───\n${loopBlock}\n\n─── LOOP PLAYBOOK ───\n- A single user request may span several assistant turns and several jobs. Continue from the latest structured session state instead of restarting.\n- Treat WORKFLOW SNAPSHOT, EXECUTION CHECKPOINT, SESSION HEAP, and AGENT LOOP STATE as the authoritative working memory for the current request.\n- Use CAPABILITY SNAPSHOT to choose the next step quickly, then use DOMAIN TYPES to write exact valid code.\n- Use WORKFLOW SNAPSHOT to understand the current boundary, recent actions, and working set before fetching more data.\n- If the user names a concrete customer, case, order, shipment, or other record that is not already in the heap, fetch it from the graph. \"Not in the current context\" is not a sufficient reason to stop.\n- Treat user-provided names as human references, not exact database keys. If the user says \"Northwind\", \"the Alpine compressor case\", or another shorthand, prefer sensible case-insensitive partial matching across likely records before concluding that nothing matches.\n- If exactly one strong partial-name match exists, use it. If several plausible partial matches exist, ask the user to choose instead of failing on an exact-equality lookup.\n- Take the minimum next step that directly advances the user's request. Do not do speculative cleanup, enrichment, or bookkeeping.\n- Reuse exact \\`taskId\\`, \\`decisionId\\`, and \\`closureId\\` values from the AGENT LOOP STATE block. Never guess or slugify IDs.\n- If the request is ambiguous or clearly multi-step, start by creating 2-4 meaningful user-visible tasks. Do not create a detailed internal checklist.\n- Keep tasks updated as the workflow advances. Complete tasks as soon as they are actually done.\n- Write the smallest straightforward code that fits the current step. Avoid defensive branches for hypothetical states that are not currently true.\n- Before asking a new question, check whether the answer is already present in the current heap, open decisions, or checkpoint.\n- If the previous step made no progress, prefer a different concrete action, a narrower fetch, or a user question instead of repeating equivalent code.\n- Use \\`loop.open_decision(...)\\` in one job to store grounded candidates, then \\`loop.close_decision(...)\\` in a later job to pick one stored candidate with \\`selectedId\\`.\n- Use \\`loop.ask_user({ type: 'input', ... })\\` only for open-ended preferences or missing free-form text that cannot be represented as a short explicit shortlist.\n- If you already have a short concrete shortlist, usually 2-7 candidates, generate code and call \\`loop.ask_user({ type: 'choice', ... })\\`. Do not downgrade that to a text input.\n- If multiple concrete records match a singular user reference such as \"the invoice\", \"the order\", \"the shipment\", or \"the request\", do not silently choose one by heuristic. Ask the user to choose unless the request already uniquely identifies the record.\n- For disambiguation between concrete known records, prefer \\`type: 'choice'\\` over \\`type: 'input'\\`. This is especially important for invoices, orders, shipments, requests, work orders, and cases.\n- For \\`type: 'choice'\\` prompts, make the options directly pickable by a human: use a stable value and a readable label that includes the identifier or title they are likely to recognize.\n- If a shortlist already exists, do not ask the user to type an exact database key or identifier manually. Present the shortlist as clickable choices instead.\n- When reasoning about free-form status strings, do not use brittle substring checks such as \\`status.includes(\"paid\")\\` because values like \\`\"unpaid\"\\` would be misclassified. Prefer explicit positive matches such as \\`unpaid\\`, \\`open\\`, or \\`overdue\\`, or exact normalized comparisons.\n- When multiple concrete records match and \\`loop.ask_user(...)\\` is available, do not stop with a plain-text question like \"Which invoice do you mean?\". Persist the live workflow and ask through \\`await loop.ask_user(...)\\` instead.\n- If the user could reasonably answer with a partial identifier such as \\`abcd\\` for \\`INV-abcd\\`, that is another sign the question should be a \\`type: 'choice'\\` prompt with visible options rather than a free-text input.\n- Never ask for approval in plain text when \\`loop.confirm(...)\\` is available. Use \\`loop.confirm(...)\\` for consequential approval.\n- When the correct next step is a loop helper action, generate code and call that helper. Do not replace it with a conversational reply.\n- If you ask the user a new question in the current job, do not also call \\`loop.close_loop(...)\\` in that same job.\n- When you need user input or approval, await \\`loop.ask_user(...)\\` or \\`loop.confirm(...)\\`. The job will pause until the user answers, then resume from that awaited call.\n- It is valid to branch on the value returned by \\`await loop.ask_user(...)\\` or \\`await loop.confirm(...)\\` after the job resumes.\n- After \\`await loop.ask_user(...)\\` returns a concrete choice, continue the workflow in the same resumed job whenever that answer is enough to act. Do not stop with placeholder text such as \"I can do that next\" or \"I'm ready to continue\".\n- After \\`await loop.confirm(...)\\` returns \\`true\\`, execute the approved mutation in that same resumed job before returning. Do not end with placeholder text like \"Approved, ready to make the change next.\"\n- Only stop immediately after a resumed prompt when the user declined, the workflow is now blocked, or you truly still need another missing piece of information.\n- If the user says stop, enough, or no further action, close the loop and end cleanly without asking another question.\n- If one clear item is already selected and the next step matters, prefer \\`loop.confirm(...)\\` over another exploratory question.\n- If one clear item is already selected and the only missing input is approval to proceed, use \\`loop.confirm(...)\\` rather than \\`loop.ask_user(...)\\`.\n- If the user already gave a usable scheduling window such as \"Tuesday morning\", treat that as enough to choose a reasonable concrete slot. Do not open another menu just to choose between nearby sub-slots unless a real conflict or hard business rule forces that follow-up.\n- For schedule changes, prefer one grounded recommendation plus one approval prompt. Avoid a second prompt for optional time-window micro-choices when you can pick a sensible default that still satisfies the user request.\n- If the user explicitly instructs you to perform a consequential action now, that instruction counts as approval. Do not add an extra confirmation step unless the user expressed hesitation, ambiguity, or asked you not to execute yet.\n- Direct imperatives such as \"cancel this order\", \"send the reminder now\", \"approve this refund\", or \"charge it now\" already authorize that exact step. Execute them directly instead of inserting \\`loop.confirm(...)\\`.\n- If the user says not to do anything irreversible yet, stop at recommendation, review, or approval. Do not collect checkout-only details like quantity, delivery notes, gift message, or optional preferences unless the user explicitly asks to move closer to purchase.\n- Once you have one solid recommendation, prefer summarizing it and asking for approval over gathering more optional preferences.\n- Prefer asking the user for the next missing input over fetching extra related data they did not ask for yet.\n- Avoid serial menus. After one clarifying choice, prefer acting on it, asking one short text question, or confirming rather than opening another menu.\n- When the user asks for a summary \"including\" concrete records such as unpaid invoices, open cases, orders, or shipments, include the actual identifiers or titles of those records in the reply, not just aggregate counts.\n- Call \\`loop.close_loop(...)\\` before stopping whenever the current workflow is completed, canceled, or clearly blocked.\n\n─── CODE RULES ───\n- Import from \\`./sandbox-tools\\`.\n- If you use \\`heap\\`, \\`loop\\`, or \\`agent_message\\`, import them explicitly from \\`./sandbox-tools\\`.\n- Write top-level executable code with \\`await\\` at top level.\n- The generated job body must be plain runnable JavaScript. The DOMAIN TYPES block is only a reference for shapes and available methods.\n- Do not write TypeScript-only syntax in executable code: no type annotations, no interfaces, no enums, no \\`as Type\\` casts, no \\`satisfies\\`, and no generic type parameters in code.\n- Generated code must be valid against the DOMAIN TYPES block above.\n- Only use classes, methods, and parameter shapes that are explicitly declared in those typedefs.\n- Never invent helper methods such as \\`find(...)\\` or unsupported parameters such as \\`id\\` when the typedefs require \\`path\\`.\n- Use \\`ClassName.get({ path })\\` only when you already know an object's graph path.\n- Use \\`ClassName.list({ limit, saveAs })\\` to load typed lists and persist reusable named lists in the heap.\n- Instance methods: \\`await instance.method_name(params)\\`.\n- Static methods: \\`await ClassName.static_method(params)\\`.\n- Global effects: \\`await effect_name(params)\\`.\n- When a child record has sparse fields, identify it through nearby graph context instead of only string-matching that child’s local fields. Prefer traversing linked customer, case, work order, part request, and shipment records over broad guesswork.\n- For blocker, delay, ETA, or \"what is holding this up?\" questions, do not stop at a parent status like \\`in_progress\\` or \\`scheduled\\` if linked dependencies exist. Trace into the likely dependency chain first: approval -> work order -> part request -> shipment -> carrier update.\n- A generic parent status is not a sufficient blocker explanation when a linked part request, approval, shipment, customs hold, or vendor delay may be the real cause.\n- If a case summary or latest customer message mentions a part, shipment, ETA, customs, vendor, approval, regulator, kit, or delay, treat that as a strong hint to inspect the linked dependency records before answering.\n- When you already found the correct parent case, inspect its linked child records even if the child summaries use different wording. Do not require a work order, part request, or shipment description to repeat the exact phrase that identified the parent case.\n- Status fields are free-form operational strings, not strict enums. Normalize spelling mentally and do not rely on brittle hard-coded sets that miss variants like \\`in-progress\\`, \\`in_progress\\`, \\`awaiting-part\\`, or \\`approval-submitted\\`.\n- Do not discard a case, work order, part request, or shipment only because its status string does not match your preferred \"open\" spelling. If the record is otherwise the clear match, inspect it.\n- Reuse \\`heap.getVar(name)\\`, \\`heap.setVar(name, value)\\`, and \\`heap.deleteVar(name)\\` only when it clearly helps the next step. Do not mirror data into the heap just for completeness.\n- Prefer \\`heap.setVar(name, value)\\` for scalars or one selected instance. Prefer \\`ClassName.list({ saveAs })\\` for lists instead of \\`heap.setVar(name, array)\\`.\n- Never write an empty array into the heap. If a filtered list is empty, keep it local or clear the previous heap value with \\`heap.deleteVar(name)\\`.\n- Prefer heap-backed state that represents the current choice or recommendation. Avoid storing extra scalar bookkeeping unless it is needed for the next concrete step.\n- Only store true sandbox instances, typed lists of sandbox instances, or scalars in the heap. Results returned by static effects like availability/search helpers are often plain JSON, not sandbox instances.\n- If a helper returns plain JSON candidates, keep them local, store only a scalar like the chosen id, or resolve the matching sandbox instance before writing it into the heap.\n- When reading heap values, prefer generated generic typings such as \\`await heap.getVar<Book[]>(\"my_books\")\\` or \\`await heap.getVar<Book>(\"selected_book\")\\`.\n- If a focused heap variable already points to a known class, read it with that exact generic type and act on it directly. Do not use \\`heap.getVar<any>(...)\\` or cast through \\`any\\` when the class is already clear from the prompt. For example, prefer \\`await heap.getVar<Order>(\"selected_order\")\\` over \\`await heap.getVar<any>(\"selected_order\")\\`.\n- Use the injected \\`loop\\` helpers when you need to manage the workflow itself:\n \\`loop.ask_user(...)\\`, \\`loop.confirm(...)\\`, \\`loop.open_decision(...)\\`, \\`loop.close_decision(...)\\`,\n \\`loop.create_task(...)\\`, \\`loop.update_task(...)\\`, \\`loop.complete_task(...)\\`, and \\`loop.close_loop(...)\\`.\n- Loop helper semantics:\n - \\`loop.open_decision(...)\\`: store explicit candidates from the current job so a later job can revisit the same decision. Keep and reuse the returned \\`decisionId\\`.\n - \\`loop.close_decision(...)\\`: resolve an open decision by choosing one stored candidate with \\`selectedId\\` and recording why. Candidates may be any JSON objects, but each one must have an \\`id\\`.\n - \\`loop.ask_user(...)\\`: pause the job and ask the user for missing input. Default to \\`type: 'input'\\`; use \\`type: 'choice'\\` only for a short explicit shortlist. Write \\`const answer = await loop.ask_user(...)\\`, then continue the same job once the user answers.\n - \\`loop.confirm(...)\\`: pause the job for approval before a consequential action. Do not simulate confirmation in plain text. Write \\`const approved = await loop.confirm(...)\\`, then branch on that approval once the job resumes.\n - \\`loop.create_task(...)\\`, \\`loop.update_task(...)\\`, \\`loop.complete_task(...)\\`: keep a short task list that later jobs can continue and finish.\n - \\`loop.close_loop(...)\\`: record the current workflow outcome with a short summary before stopping. Do not call it in the same job that opens a new user prompt unless the workflow is explicitly blocked. This does not end the session forever.\n- Avoid \\`as any\\` and other broad casts when the DOMAIN TYPES block already tells you the correct class or list type.\n- Prefer manipulating heap-backed instances and typed lists instead of returning raw JSON blobs or object IDs unless the user explicitly asks for them.\n- If the user expects an answer after the job runs, the final \\`return\\` value must be either a short natural-language string or an object with a top-level \\`reply\\` string.\n- Prefer \\`agent_message({ reply, show })\\` when you want to leave a user-facing answer and optionally show heap-backed records in the UI.\n- When it helps the UI show specific heap-backed results, you may instead return:\n \\`{ reply: string, show: { entryPaths?: string[], listNames?: string[], variableNames?: string[] } }\\`\n- If you create or load objects the user should see, save them in the heap and return references to them through \\`show\\` instead of serializing full objects.\n- Do not return bare structured JSON, low-level diagnostics, or database-shaped payloads as the final answer unless the user explicitly asks for them.\n- Prefer simple executable JavaScript over clever interpolation. Avoid nested template literals or unusually dense inline expressions when a small temporary variable or string concatenation would be clearer and safer.\n- Use \\`console.log()\\` only for intermediate diagnostics, not for the final user-facing answer.`;\n}\n"]}
package/dist/cli/index.js CHANGED
@@ -8941,7 +8941,7 @@ function manifestGuideEndToEndSection() {
8941
8941
  | 2 | \`granular build\` | Manifest **uploaded**; ontology version created or reused; build run compiles it; errors surface here |
8942
8942
  | 3 | (Optional) Run your **effects host** \u2014 e.g. \`npx tsx granular-effects.ts\` \u2014 calling \`registerEffects(sandboxId, \u2026)\` | Effect **handlers** attached in **your** process |
8943
8943
  | 4 | \`new Granular({ apiKey })\` then \`connect({ ontology, environment, userId, permissions })\` | **\`Environment\`** for that ontology environment slot |
8944
- | 5 | \`recordObject\` / \`recordObjects\` | **Records** stored with correct fields and relationship keys |
8944
+ | 5 | \`recordObject\` / \`recordObjects\` | **Records** stored with correct fields and relationship keys. \`recordObjects\` chunks to the control plane (default 100 rows/request); pass \`onChunkComplete\` / \`concurrency\` for UI progress. For async bulk loads use \`enqueueRecordImport\` + import status APIs. |
8945
8945
  | 6 | \`submitJob(\`\u2026\`)\` with imports from \`./sandbox-tools\` | **Jobs** run; may call **effects** \u2192 your handlers execute and return results |
8946
8946
 
8947
8947
  **Accuracy tip:** After changing the manifest, always **re-build** before assuming generated types, \`./sandbox-tools\` names, or effect signatures match the file on disk.`;
@@ -14961,8 +14961,8 @@ ${effectMetamodelTable}
14961
14961
  |-----|---------|
14962
14962
  | \`environmentId\`, \`sandboxId\`, \`apiEndpoint\`, \u2026 | Session context. |
14963
14963
  | \`applyManifest(manifest)\` | Apply manifest operations at runtime (alternative to CLI build for dynamic ontologies). |
14964
- | \`recordObject\` / \`recordObjects\` | Upsert instances and relationships. |
14965
- | \`enqueueRecordImport\`, \`listRecordImports\`, \`getRecordImportSummary\`, \u2026 | Background bulk import. |
14964
+ | \`recordObject\` / \`recordObjects\` | Upsert instances and relationships. \`recordObjects\` uses chunked HTTP batch writes (default 100 rows/chunk); optional \`onChunkComplete\`, \`batchSize\`, \`concurrency\`. |
14965
+ | \`enqueueRecordImport\`, \`listRecordImports\`, \`getRecordImportSummary\`, \u2026 | **Async** bulk import (worker queue + aggregate progress). Prefer when loads are huge and fire-and-forget is OK. |
14966
14966
  | \`graphql(query, variables?)\` | **GraphQL** \u2014 see dedicated subsection below. |
14967
14967
  | \`defineRelationship\`, \`getRelationships\`, \`attach\`, \`detach\`, \`listRelated\` | Imperative relationship operations (same ideas as manifest \`defineRelationship\`). |
14968
14968
  | \`submitJob(code)\` | Run code in the sandbox; import from \`./sandbox-tools\`. |
@@ -15502,6 +15502,7 @@ edit granular.json -> granular build -> granular document -> run tests -> option
15502
15502
 
15503
15503
  - Default auth story: \`granular login\`. Manual \`.env.local\` editing is fallback guidance only.
15504
15504
  - Read \`GRANULAR_SANDBOX.md\` before writing \`recordObject\` payloads or relationship keys.
15505
+ - Large ingests: use \`recordObjects(rows, { onChunkComplete, concurrency })\` for synchronous chunked writes with progress, or \`enqueueRecordImport\` + \`getRecordImport\` for async queue-based bulk loads.
15505
15506
  - Build failures should be mapped to the exact class, relationship, or effect declaration that caused them.
15506
15507
  - If the user starts from the control plane UI, converge back to the same repo state and the same CLI commands.
15507
15508
  `
@@ -17792,6 +17793,83 @@ var WSClient = class {
17792
17793
  }
17793
17794
  };
17794
17795
 
17796
+ // src/prompt-utils.ts
17797
+ function asRecord(value) {
17798
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
17799
+ return value;
17800
+ }
17801
+ function normalizePromptText(value) {
17802
+ return value.toLowerCase().replace(/[_-]+/g, " ").replace(/[^a-z0-9]+/g, " ").trim();
17803
+ }
17804
+ function extractPromptTokens(value) {
17805
+ return normalizePromptText(value).split(/\s+/).map((token) => token.trim()).filter((token) => token.length > 0);
17806
+ }
17807
+ function scorePromptChoiceMatch(answer, answerTokens, option) {
17808
+ const value = typeof option === "string" ? option : typeof option?.value === "string" ? option.value : "";
17809
+ const label = typeof option === "string" ? option : typeof option?.label === "string" ? option.label : "";
17810
+ const description = typeof option === "string" ? "" : typeof option?.description === "string" ? option.description : "";
17811
+ const haystack = normalizePromptText([value, label, description].filter(Boolean).join(" "));
17812
+ if (!haystack) return { score: 0, resolvedValue: value || label || null };
17813
+ let score = 0;
17814
+ if (value && normalizePromptText(value) === answer) score += 12;
17815
+ if (label && normalizePromptText(label) === answer) score += 10;
17816
+ if (answer.includes(haystack)) score += 8;
17817
+ if (haystack.includes(answer)) score += 6;
17818
+ for (const token of answerTokens) {
17819
+ if (value && normalizePromptText(value).includes(token)) score += 10;
17820
+ if (label && normalizePromptText(label).includes(token)) score += 8;
17821
+ if (description && normalizePromptText(description).includes(token)) score += 5;
17822
+ }
17823
+ return { score, resolvedValue: value || label || null };
17824
+ }
17825
+ function normalizePromptType(raw) {
17826
+ const type = typeof raw?.type === "string" ? raw.type : null;
17827
+ const kind = typeof raw?.kind === "string" ? raw.kind : null;
17828
+ const promptType = typeof raw?.promptType === "string" ? raw.promptType : null;
17829
+ if (type === "confirm" || type === "choice" || type === "input") return type;
17830
+ if (kind === "confirm" || kind === "choice" || kind === "input") return kind;
17831
+ if (promptType === "confirm" || promptType === "choice" || promptType === "input") return promptType;
17832
+ return "input";
17833
+ }
17834
+ function normalizePrompt(rawValue) {
17835
+ const raw = asRecord(rawValue);
17836
+ if (!raw) return null;
17837
+ const promptRecord = asRecord(raw.prompt);
17838
+ const source = promptRecord || raw;
17839
+ const id = typeof source.id === "string" ? source.id : typeof raw.id === "string" ? raw.id : typeof raw.promptId === "string" ? raw.promptId : "";
17840
+ if (!id) return null;
17841
+ return {
17842
+ id,
17843
+ type: normalizePromptType(source === raw ? raw : { ...raw, ...source }),
17844
+ title: typeof source.title === "string" ? source.title : "Input required",
17845
+ message: typeof source.message === "string" ? source.message : "",
17846
+ options: Array.isArray(source.options) ? source.options : void 0,
17847
+ defaultValue: source.defaultValue,
17848
+ placeholder: typeof source.placeholder === "string" ? source.placeholder : void 0,
17849
+ allowEmpty: typeof source.allowEmpty === "boolean" ? source.allowEmpty : void 0,
17850
+ metadata: asRecord(source.metadata) || void 0
17851
+ };
17852
+ }
17853
+ function resolvePromptAnswer(prompt3, answer) {
17854
+ if (!prompt3) return answer;
17855
+ if (prompt3.type === "confirm") {
17856
+ if (typeof answer === "boolean") return answer;
17857
+ if (typeof answer === "string") return /^(yes|y|true|confirm|ok)/i.test(answer.trim());
17858
+ return Boolean(answer);
17859
+ }
17860
+ if (prompt3.type === "choice" && Array.isArray(prompt3.options) && typeof answer === "string") {
17861
+ const normalized = normalizePromptText(answer);
17862
+ const tokens = extractPromptTokens(answer);
17863
+ let best = { score: -1, resolvedValue: null };
17864
+ for (const option of prompt3.options) {
17865
+ const scored = scorePromptChoiceMatch(normalized, tokens, option);
17866
+ if (scored.score > best.score) best = scored;
17867
+ }
17868
+ if (best.resolvedValue) return best.resolvedValue;
17869
+ }
17870
+ return answer;
17871
+ }
17872
+
17795
17873
  // src/session.ts
17796
17874
  var Session = class {
17797
17875
  client;
@@ -17806,6 +17884,8 @@ var Session = class {
17806
17884
  effects = /* @__PURE__ */ new Map();
17807
17885
  /** Last known tools for diffing */
17808
17886
  lastKnownTools = /* @__PURE__ */ new Map();
17887
+ /** Last seen live prompts, keyed by prompt id, for answer normalization */
17888
+ promptCache = /* @__PURE__ */ new Map();
17809
17889
  constructor(client, clientId) {
17810
17890
  this.client = client;
17811
17891
  this.clientId = clientId || `client_${Date.now()}`;
@@ -17963,7 +18043,10 @@ var Session = class {
17963
18043
  * Respond to a prompt request from the sandbox
17964
18044
  */
17965
18045
  async answerPrompt(promptId, answer) {
17966
- await this.client.call("prompt.answer", { promptId, answer, value: answer });
18046
+ const prompt3 = this.promptCache.get(promptId);
18047
+ const resolvedAnswer = resolvePromptAnswer(prompt3, answer);
18048
+ this.promptCache.delete(promptId);
18049
+ await this.client.call("prompt.answer", { promptId, answer: resolvedAnswer, value: resolvedAnswer });
17967
18050
  }
17968
18051
  /**
17969
18052
  * Get the current list of available effects.
@@ -18287,18 +18370,9 @@ import { ${allImports} } from "./sandbox-tools";
18287
18370
  this.checkForToolChanges();
18288
18371
  });
18289
18372
  const emitPrompt = (payload) => {
18290
- const raw = payload;
18291
- const prompt3 = raw.prompt || {
18292
- id: typeof raw.id === "string" ? raw.id : String(raw.promptId || ""),
18293
- type: raw.type === "confirm" || raw.type === "choice" || raw.type === "input" ? raw.type : raw.promptType === "confirm" || raw.promptType === "choice" ? raw.promptType : "input",
18294
- title: typeof raw.title === "string" ? raw.title : "Input required",
18295
- message: typeof raw.message === "string" ? raw.message : "",
18296
- options: raw.options,
18297
- defaultValue: raw.defaultValue,
18298
- placeholder: raw.placeholder,
18299
- allowEmpty: raw.allowEmpty,
18300
- metadata: raw.metadata
18301
- };
18373
+ const prompt3 = normalizePrompt(payload);
18374
+ if (!prompt3) return;
18375
+ this.promptCache.set(prompt3.id, prompt3);
18302
18376
  this.emit("prompt", prompt3);
18303
18377
  };
18304
18378
  this.client.on("prompt", emitPrompt);
@@ -18794,6 +18868,28 @@ var STANDARD_MODULES_OPERATIONS = [
18794
18868
  var BUILTIN_MODULES = {
18795
18869
  "standard_modules": STANDARD_MODULES_OPERATIONS
18796
18870
  };
18871
+ var DEFAULT_DIRECT_RECORD_OBJECTS_REQUEST_BATCH_SIZE = 100;
18872
+ var MAX_RECORD_OBJECTS_CONCURRENCY = 16;
18873
+ var DEFAULT_DIRECT_RECORD_OBJECTS_RETRY_COUNT = 3;
18874
+ var DEFAULT_DIRECT_RECORD_OBJECTS_RETRY_DELAY_MS = 1e3;
18875
+ function planRecordObjectsChunks(records, batchSize) {
18876
+ const total = records.length;
18877
+ const size = Math.max(1, Math.min(batchSize, total));
18878
+ const chunkCount = Math.ceil(total / size);
18879
+ const plans = [];
18880
+ for (let offset = 0, chunkIndex = 0; offset < total; offset += size, chunkIndex += 1) {
18881
+ const slice = records.slice(offset, offset + size);
18882
+ plans.push({ chunkIndex, chunkCount, offset, slice });
18883
+ }
18884
+ return plans;
18885
+ }
18886
+ function sleep(ms) {
18887
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
18888
+ }
18889
+ function isRetryableRecordObjectsError(error2) {
18890
+ const message = error2 instanceof Error ? error2.message : String(error2);
18891
+ return /worker restarted mid-request|econnreset|network|socket connection was closed unexpectedly|timed out/i.test(message);
18892
+ }
18797
18893
  function computeEffectKey2(effect) {
18798
18894
  const attachedClass = effect.className?.trim();
18799
18895
  if (!attachedClass) {
@@ -19751,24 +19847,101 @@ var Environment = class extends Session {
19751
19847
  /**
19752
19848
  * Batch version of `recordObject()`.
19753
19849
  *
19754
- * Sends several upserts through the control-plane batch endpoint so the
19755
- * server can collapse the graph mutations into far fewer round trips.
19850
+ * Sends rows through the control-plane **`/records/batch`** endpoint in **chunks** (default
19851
+ * **100** records per HTTP request) so individual requests stay bounded and gateway timeouts are
19852
+ * unlikely. Each chunk is retried on transient network / worker errors.
19853
+ *
19854
+ * Use the optional second argument to:
19855
+ * - **`batchSize`** — rows per POST (smaller = more progress events; larger = fewer round trips).
19856
+ * - **`concurrency`** — run up to N chunk POSTs in parallel (capped at 16) when you want lower wall time.
19857
+ * - **`onChunkComplete`** — hook for UIs after each chunk succeeds (row order in the returned array
19858
+ * always matches `records`; chunk **completion** order may differ when `concurrency > 1`).
19859
+ *
19860
+ * For **asynchronous** ingestion with worker-side batching and aggregate counters (`queued`,
19861
+ * `completed`, …), use **`enqueueRecordImport`** and poll **`getRecordImport`** /
19862
+ * **`getRecordImportSummary`** — best for very large fire-and-forget loads when immediate
19863
+ * synchronous commit of every row is not required.
19756
19864
  */
19757
- async recordObjects(records) {
19865
+ async recordObjects(records, options) {
19758
19866
  if (!Array.isArray(records) || records.length === 0) {
19759
19867
  return [];
19760
19868
  }
19761
- const response = await this.controlPlaneRequest(
19762
- `/control/environments/${this.environmentId}/records/batch`,
19763
- {
19764
- method: "POST",
19765
- body: JSON.stringify({ records })
19766
- }
19869
+ const batchSize = Math.max(
19870
+ 1,
19871
+ Math.min(
19872
+ records.length,
19873
+ options?.batchSize ?? DEFAULT_DIRECT_RECORD_OBJECTS_REQUEST_BATCH_SIZE
19874
+ )
19767
19875
  );
19768
- return Array.isArray(response.items) ? response.items : [];
19876
+ const concurrency = Math.min(
19877
+ MAX_RECORD_OBJECTS_CONCURRENCY,
19878
+ Math.max(1, options?.concurrency ?? 1)
19879
+ );
19880
+ const plans = planRecordObjectsChunks(records, batchSize);
19881
+ const total = records.length;
19882
+ const results = new Array(total);
19883
+ const onChunk = options?.onChunkComplete;
19884
+ for (let waveStart = 0; waveStart < plans.length; waveStart += concurrency) {
19885
+ const wave = plans.slice(waveStart, waveStart + concurrency);
19886
+ await Promise.all(
19887
+ wave.map(async (plan) => {
19888
+ const { items, durationMs } = await this.executeRecordObjectsChunk(plan.slice);
19889
+ if (items.length !== plan.slice.length) {
19890
+ throw new Error(
19891
+ `recordObjects: chunk ${plan.chunkIndex + 1} returned ${items.length} results, expected ${plan.slice.length}`
19892
+ );
19893
+ }
19894
+ for (let index = 0; index < items.length; index += 1) {
19895
+ results[plan.offset + index] = items[index];
19896
+ }
19897
+ if (onChunk) {
19898
+ const info2 = {
19899
+ chunkIndex: plan.chunkIndex,
19900
+ totalChunks: plan.chunkCount,
19901
+ offset: plan.offset,
19902
+ recordCount: plan.slice.length,
19903
+ durationMs,
19904
+ results: items
19905
+ };
19906
+ await onChunk(info2);
19907
+ }
19908
+ })
19909
+ );
19910
+ }
19911
+ return results;
19912
+ }
19913
+ async executeRecordObjectsChunk(chunk) {
19914
+ const wallStart = Date.now();
19915
+ let lastError;
19916
+ for (let attempt = 1; attempt <= DEFAULT_DIRECT_RECORD_OBJECTS_RETRY_COUNT; attempt += 1) {
19917
+ try {
19918
+ const response = await this.controlPlaneRequest(
19919
+ `/control/environments/${this.environmentId}/records/batch`,
19920
+ {
19921
+ method: "POST",
19922
+ body: JSON.stringify({ records: chunk })
19923
+ }
19924
+ );
19925
+ const items = Array.isArray(response.items) ? response.items : [];
19926
+ return { items, durationMs: Date.now() - wallStart };
19927
+ } catch (error2) {
19928
+ lastError = error2;
19929
+ if (!isRetryableRecordObjectsError(error2) || attempt === DEFAULT_DIRECT_RECORD_OBJECTS_RETRY_COUNT) {
19930
+ throw error2;
19931
+ }
19932
+ await sleep(DEFAULT_DIRECT_RECORD_OBJECTS_RETRY_DELAY_MS * attempt);
19933
+ }
19934
+ }
19935
+ throw lastError instanceof Error ? lastError : new Error(String(lastError));
19769
19936
  }
19770
19937
  /**
19771
- * Queue a background record import for this environment.
19938
+ * Queue a background record import for this environment (async worker pipeline).
19939
+ *
19940
+ * **vs `recordObjects`:** this path accepts the full payload in one request, returns an
19941
+ * **`importId`**, and processes rows in the background — use **`getRecordImport`** /
19942
+ * **`getRecordImportSummary`** for progress. Choose it for large bulk loads where you do not
19943
+ * need every row committed before the HTTP call returns. Use **`recordObjects`** when you need
19944
+ * synchronous upserts and fine-grained chunk progress via **`onChunkComplete`**.
19772
19945
  */
19773
19946
  async enqueueRecordImport(records, options = {}) {
19774
19947
  return this.controlPlaneRequest(