{"version":3,"file":"index.mjs","names":["Agent","ensureDockerImage"],"sources":["../src/given/a_workspace.ts","../src/given/copy_to_workspace.ts","../src/given/the_prompt.ts","../src/when/executing_the_agent.ts","../src/given/agent.ts"],"sourcesContent":["import { mkdir, mkdtemp, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport type { AgentContext } from \"../types.js\";\n\nexport const AGENTS_GWT_TMP_ROOT = join(tmpdir(), \".agents-gwt\");\n\nexport async function a_workspace(this: AgentContext): Promise<void> {\n  await mkdir(AGENTS_GWT_TMP_ROOT, { recursive: true });\n  this.workspace = await mkdtemp(join(AGENTS_GWT_TMP_ROOT, \"ws-\"));\n}\n\nexport async function cleanup_workspace(this: AgentContext): Promise<void> {\n  if (this.workspace === undefined || this.workspace === \"\") {\n    return;\n  }\n\n  await rm(this.workspace, { recursive: true, force: true });\n}\n","import { copyFile, mkdir, readdir, stat } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport type CopyToWorkspaceOptions = {\n  readonly from?: string;\n  readonly base?: string;\n};\n\nexport async function copy_to_workspace(\n  workspace: string,\n  globs: readonly string[],\n  options?: CopyToWorkspaceOptions,\n): Promise<void> {\n  if (globs.length === 0) {\n    throw new Error(\"copy_to_workspace: globs must not be empty\");\n  }\n\n  const from = await resolveSourceRoot(options);\n  const resolvedWorkspace = resolve(workspace);\n  const base = options?.base;\n  const copies: Array<{ source: string; destination: string }> = [];\n  const destinationSources = new Map<string, string>();\n\n  for (const glob of globs) {\n    const matches = await expandGlob(from, glob);\n    if (matches.length === 0) {\n      throw new Error(`copy_to_workspace: glob \"${glob}\" matched no files under ${from}`);\n    }\n\n    for (const relativePath of matches) {\n      const destinationRelative = base === undefined ? relativePath : stripBase(relativePath, base);\n      assertSafeRelative(destinationRelative, \"destination\");\n\n      const source = resolve(from, relativePath);\n      const destination = resolve(resolvedWorkspace, destinationRelative);\n      if (!isInsideRoot(resolvedWorkspace, destination)) {\n        throw new Error(`copy_to_workspace: destination escapes workspace: ${destinationRelative}`);\n      }\n\n      const existingSource = destinationSources.get(destinationRelative);\n      if (existingSource !== undefined) {\n        if (existingSource === source) {\n          continue;\n        }\n        throw new Error(\n          `copy_to_workspace: destination \"${destinationRelative}\" maps to multiple files`,\n        );\n      }\n\n      destinationSources.set(destinationRelative, source);\n      copies.push({ source, destination });\n    }\n  }\n\n  for (const { source, destination } of copies) {\n    await mkdir(dirname(destination), { recursive: true });\n    await copyFile(source, destination);\n  }\n}\n\nasync function resolveSourceRoot(options: CopyToWorkspaceOptions | undefined): Promise<string> {\n  const from = options?.from;\n  if (from !== undefined && isAbsolute(from)) {\n    return resolve(from);\n  }\n\n  const specDir = await currentSpecDirectory();\n  if (from === undefined) {\n    return specDir;\n  }\n\n  return resolve(specDir, from);\n}\n\nasync function currentSpecDirectory(): Promise<string> {\n  const { expect } = await import(\"vitest\");\n  const testPath = expect.getState().testPath;\n  if (testPath === undefined || testPath === \"\") {\n    throw new Error(\n      \"copy_to_workspace: cannot resolve the spec directory; pass options.from or call from a Vitest test\",\n    );\n  }\n\n  const specFile = testPath.startsWith(\"file:\") ? fileURLToPath(testPath) : testPath;\n  return dirname(specFile);\n}\n\nasync function expandGlob(from: string, glob: string): Promise<string[]> {\n  const posixGlob = glob.replaceAll(\"\\\\\", \"/\");\n  const matcher = globToRegExp(posixGlob);\n  const prefixSegments = globStaticPrefix(posixGlob);\n  const walkRoot = prefixSegments.length === 0 ? from : join(from, ...prefixSegments);\n  if (!isInsideRootOrEqual(from, walkRoot)) {\n    throw new Error(`copy_to_workspace: glob \"${glob}\" escapes source root`);\n  }\n\n  let walkInfo;\n  try {\n    walkInfo = await stat(walkRoot);\n  } catch (error: unknown) {\n    if (isEnoent(error)) {\n      return [];\n    }\n    throw error;\n  }\n\n  if (walkInfo.isFile()) {\n    const relativePath = toPosixRelative(from, walkRoot);\n    if (!matcher.test(relativePath)) {\n      return [];\n    }\n    return [relativePath];\n  }\n\n  if (!walkInfo.isDirectory()) {\n    return [];\n  }\n\n  const names = await readdir(walkRoot, { recursive: true });\n  const matches: string[] = [];\n\n  for (const name of names) {\n    const absolutePath = join(walkRoot, name);\n    if (!isInsideRoot(from, absolutePath)) {\n      throw new Error(`copy_to_workspace: matched path escapes source root: ${absolutePath}`);\n    }\n\n    const info = await stat(absolutePath);\n    const relativePath = toPosixRelative(from, absolutePath);\n    if (!info.isFile() || !matcher.test(relativePath)) {\n      continue;\n    }\n\n    matches.push(relativePath);\n  }\n\n  return matches;\n}\n\nfunction globStaticPrefix(glob: string): string[] {\n  const segments: string[] = [];\n  for (const segment of glob.split(\"/\")) {\n    if (segment === \"\" || segment.includes(\"*\") || segment.includes(\"?\")) {\n      break;\n    }\n    segments.push(segment);\n  }\n  return segments;\n}\n\nfunction toPosixRelative(from: string, absolutePath: string): string {\n  return relative(from, absolutePath).split(sep).join(\"/\");\n}\n\nfunction isInsideRootOrEqual(root: string, absolutePath: string): boolean {\n  return resolve(root) === resolve(absolutePath) || isInsideRoot(root, absolutePath);\n}\n\nfunction isInsideRoot(root: string, absolutePath: string): boolean {\n  const rel = relative(resolve(root), resolve(absolutePath));\n  return rel !== \"\" && !rel.startsWith(`..${sep}`) && rel !== \"..\" && !rel.startsWith(\"../\");\n}\n\nfunction assertSafeRelative(relativePath: string, label: string): void {\n  const segments = relativePath.split(\"/\");\n  if (\n    segments.length === 0 ||\n    segments.some((segment) => segment === \"\" || segment === \".\" || segment === \"..\")\n  ) {\n    throw new Error(`copy_to_workspace: ${label} is not a safe relative path: ${relativePath}`);\n  }\n}\n\nfunction stripBase(relativePath: string, base: string): string {\n  const pathSegments = relativePath.split(\"/\");\n  const baseSegments = base\n    .replaceAll(\"\\\\\", \"/\")\n    .split(\"/\")\n    .filter((segment) => segment !== \"\");\n\n  if (!matchesBasePrefix(pathSegments, baseSegments)) {\n    throw new Error(`copy_to_workspace: path \"${relativePath}\" does not match base \"${base}\"`);\n  }\n\n  const destinationSegments = pathSegments.slice(baseSegments.length);\n  if (\n    destinationSegments.length === 0 ||\n    destinationSegments.some((segment) => segment === \"\" || segment === \"..\")\n  ) {\n    throw new Error(\n      `copy_to_workspace: stripping base \"${base}\" from \"${relativePath}\" left an empty destination`,\n    );\n  }\n\n  return destinationSegments.join(\"/\");\n}\n\nfunction matchesBasePrefix(\n  pathSegments: readonly string[],\n  baseSegments: readonly string[],\n): boolean {\n  if (pathSegments.length <= baseSegments.length) {\n    return false;\n  }\n\n  for (const [index, baseSegment] of baseSegments.entries()) {\n    const pathSegment = pathSegments[index];\n    if (pathSegment === undefined) {\n      return false;\n    }\n    if (baseSegment !== \"*\" && baseSegment !== pathSegment) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\nfunction globToRegExp(glob: string): RegExp {\n  const pattern = glob.replaceAll(\"\\\\\", \"/\");\n  let regex = \"^\";\n  let index = 0;\n\n  while (index < pattern.length) {\n    const char = pattern[index];\n    if (char === undefined) {\n      break;\n    }\n\n    if (char === \"*\" && pattern[index + 1] === \"*\") {\n      if (pattern[index + 2] === \"/\") {\n        regex += \"(?:.*/)?\";\n        index += 3;\n        continue;\n      }\n\n      regex += \".*\";\n      index += 2;\n      continue;\n    }\n\n    if (char === \"*\") {\n      regex += \"[^/]*\";\n      index += 1;\n      continue;\n    }\n\n    if (char === \"?\") {\n      regex += \"[^/]\";\n      index += 1;\n      continue;\n    }\n\n    regex += escapeRegExp(char);\n    index += 1;\n  }\n\n  return new RegExp(`${regex}$`);\n}\n\nfunction escapeRegExp(char: string): string {\n  return char.replaceAll(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction isEnoent(error: unknown): boolean {\n  return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\";\n}\n","import type { AgentContext } from \"../types.js\";\n\nexport function the_prompt(prompt: string) {\n  return function (this: AgentContext): void {\n    this.prompt = prompt;\n  };\n}\n","import type { AgentContext } from \"../types.js\";\n\nexport async function executing_the_agent(this: AgentContext): Promise<void> {\n  if (this.workspace === undefined || this.workspace === \"\") {\n    throw new Error(\"executing_the_agent requires this.workspace; use a_workspace in given\");\n  }\n\n  if (this.prompt === undefined || this.prompt === \"\") {\n    throw new Error(\"executing_the_agent requires this.prompt; use the_prompt(...) in given\");\n  }\n\n  if (this.agent === undefined) {\n    throw new Error(\n      \"executing_the_agent requires this.agent; use agent({ name, model }) in withAspect\",\n    );\n  }\n\n  this.agentResult = await this.agent.run({\n    workspace: this.workspace,\n    prompt: this.prompt,\n    image: this.image,\n    ...(this.model !== undefined ? { model: this.model } : {}),\n  });\n}\n","import { Agent, ensureDockerImage, type RegistryOptions } from \"clanker-cleanroom\";\n\nimport type { AgentContext } from \"../types.js\";\n\nexport type ConfigureAgentOptions = {\n  /** Registered stock short name or a registry tag (`cursor:node`). */\n  name: string;\n  model?: string;\n  /** Override the resolved Docker image tag. */\n  image?: string;\n} & RegistryOptions;\n\nexport function agent(options: ConfigureAgentOptions) {\n  return async function (this: AgentContext): Promise<void> {\n    const registryOptions =\n      options.packageRoot !== undefined ? { packageRoot: options.packageRoot } : {};\n    const resolved = new Agent(options.name, registryOptions);\n\n    this.agent = resolved;\n    this.image = options.image ?? resolved.image;\n\n    if (options.model !== undefined) {\n      this.model = options.model;\n    }\n\n    await ensureDockerImage(this.image);\n  };\n}\n"],"mappings":"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"}