Skip to content

feat(agent-profile-cell): AGENT_PROFILE_KINDS + toAgentProfileJson + buildSandboxAgentProfileCell#86

Merged
drewstone merged 1 commit into
mainfrom
feat/agent-profile-cell-consumer-helpers
May 22, 2026
Merged

feat(agent-profile-cell): AGENT_PROFILE_KINDS + toAgentProfileJson + buildSandboxAgentProfileCell#86
drewstone merged 1 commit into
mainfrom
feat/agent-profile-cell-consumer-helpers

Conversation

@drewstone
Copy link
Copy Markdown
Contributor

Closes #82.

What

Two pieces of boilerplate every product consuming buildAgentProfileCell has been duplicating — gtm-agent#137, blueprint-agent#1756 / #1757:

  1. A JSON.parse(JSON.stringify(value)) helper that canonicalizes an arbitrary sandbox-SDK AgentProfile into AgentProfileJson, with a fail-loud error when the profile is not JSON-serializable.
  2. The magic string 'sandbox-agent-profile' for sourceProfile.kind.

Both belong here so the cross-product cell join (same canonical profile hashes to the same sourceProfile.hash across products) is enforced by the type system, not by every consumer remembering to do it right.

API additions

export const AGENT_PROFILE_KINDS = {
  SANDBOX_AGENT_PROFILE: 'sandbox-agent-profile',
} as const
export type AgentProfileKind = (typeof AGENT_PROFILE_KINDS)[keyof typeof AGENT_PROFILE_KINDS]

export function toAgentProfileJson(value: unknown): AgentProfileJson

export interface SandboxAgentProfileLike { name: string; version: string; [key: string]: unknown }

export async function buildSandboxAgentProfileCell(
  profile: SandboxAgentProfileLike,
  input: Omit<AgentProfileCellInput, 'profileId' | 'sourceProfile'>,
): Promise<AgentProfileCell>

buildSandboxAgentProfileCell is the higher-level wrapper — hard-codes profileId = \${name}@${version}`and thesandbox-agent-profilekind. The manualbuildAgentProfileCell` call stays for advanced cases (custom kinds, pre-computed source hashes, alternate profileId conventions).

Verification

  • tsc --noEmit clean.
  • Package suite: 1317/1317 pass (11 new tests for the helpers).
  • Cross-product invariant explicitly tested: a hand-rolled buildAgentProfileCell call following the documented README recipe produces the identical sourceProfile.hash + cellId as buildSandboxAgentProfileCell. Two products converging on this helper are guaranteed to hash the same canonical profile identically.

Downstream

  • gtm-agent's eval/agent-profile-cell.ts can delete its local toAgentProfileJson and import the canonical one.
  • blueprint-agent's scripts/experiments/lib/agent-profile-cell.ts (currently shipping its own sandboxAgentProfileToJson + the magic string) will follow up with a PR collapsing the duplication.

…fileCell

Closes #82.

Two pieces of boilerplate every product consuming `buildAgentProfileCell`
has been duplicating — gtm-agent #137, blueprint-agent #1756/#1757:

  1. A `JSON.parse(JSON.stringify(value))` helper that canonicalizes an
     arbitrary sandbox-SDK `AgentProfile` into `AgentProfileJson`, with a
     fail-loud error when the profile is not JSON-serializable.
  2. The magic string `'sandbox-agent-profile'` for `sourceProfile.kind`.

Both belong here so the cross-product cell join (same canonical profile
hashes to the same `sourceProfile.hash` across products) is enforced by
the type system, not by every consumer remembering to do it right.

Exports:
- `AGENT_PROFILE_KINDS` — typed const with `SANDBOX_AGENT_PROFILE`. Open
  for extension when new profile shapes land.
- `toAgentProfileJson(value)` — JSON round-trip with `AgentProfileCell-
  ValidationError` on functions / BigInt / cycles / `undefined` results.
- `buildSandboxAgentProfileCell(profile, rest)` — higher-level wrapper
  that hard-codes `profileId = ${name}@${version}` and the sandbox kind,
  reserving the manual `buildAgentProfileCell` call for advanced cases.

11 new tests; full suite 1326/1326 pass; `tsc --noEmit` clean. Tests
explicitly verify the cross-product invariant — a hand-rolled cell call
following the README recipe produces the identical hash to the helper.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Export toAgentProfileJson + canonical sourceProfile.kind constants — every consumer is duplicating both

1 participant