#debugging an agent

1 messages · Page 1 of 1 (latest)

pulsar bloom
#

are you able to share the code? especially the object you're giving the llm that has the Container.write() being called?

last echo
#
// src/index.ts
  @func()
  writeTests(source: Directory): Container {
    const prompt = dag.currentModule().source().file("prompts/write_tests.md");
    const before = dag.workspace(source);
    return dag.llm()
      .withWorkspace(before)
      .withPromptFile(prompt)
      .container();
  }
#
// workspace/src/index.ts
import { dag, Container, Directory, File, object, func } from "@dagger.io/dagger"

@object()
export class Workspace {

  source: Directory;
  container: Container;

  constructor(source: Directory) {
    this.source = source;

    // create a Dagger cache volume for dependencies
    const nodeCache = dag.cacheVolume("node");
    this.container = dag
      .container()
      .from("node:22-slim")
      .withMountedCache("/root/.npm", nodeCache)
      .withDirectory("/src", this.source)
      .withWorkdir("/src")
      .withExec(["npm", "install"]);
  }

  @func()
  test(): Container {
    return this.container
      .withExec(["npm", "run", "test", "--", "--run"])
  }

  @func()
  coverage(): Container {
    return this.container
      .withExec(["npm", "run", "test", "--", "--run", "--coverage"])
  }

  @func()
  async tree(): Promise<string> {
    return await dag.container()
      .from("alpine:3")
      .withDirectory("/workspace", this.source)
      .withExec(["tree", "/workspace"])
      .stdout();
  }

  @func()
  async read(path: string): Promise<string| null> {
      try {
        return await this.container
          .file(path)
          .contents();
      } catch (error) {
        console.error(`Encountered an error reading ${path}: ${error}`);
        return null;
      }
  }

  @func()
  write(path: string, contents: string): File {
    return this.container
      .withNewFile(path, contents)
      .file(path);
  }
}
pulsar bloom
#

ah got it 🙂
on functions where you modify state, you want to write state and return self, so

@func()
  write(path: string, contents: string): File {
    return this.container
      .withNewFile(path, contents)
      .file(path);
  }

becomes

@func()
  write(path: string, contents: string): Workspace {
    this.container = this.container.withNewFile(path, contents);
    return this;
  }
last echo
#

Welp 👌 thank you! And that should be obvious in hindsight

#

I feel like im still trying to wrap my head around the programming model

#

This is something i feel like I’m missing in the docs. There’s a lot of “this how you do X”, but i feel like I’m missing the theory part

last echo
#

hm, export is still not actually writing anything

#

ok, at least ive got errors in the trace now

#

"Call: Query has no such field: "workspace"" this seems sus

pulsar bloom
#

Oh the main function should be .workspace().container() instead of just .container() I think

last echo
#

because i want to return the WORKSPACE container, not the llm container

#

like now i have

@func()
writeTests(source: Directory): Container {
  const prompt = dag.currentModule().source().file("prompts/write_tests.md");
  const before = dag.workspace(source);
  
  return dag.llm()
    .withWorkspace(before)
    .withPromptFile(prompt)
    .container();
}

you're saying i should be accessing the workspace after fromPrompt and then returning that container

pulsar bloom
last echo
#

feel like i had this exact conversation with @dull falcon earlier today about trying to vet dagger modules

split iron
#

I pushed some changes to try to align with some other examples but I clearly broke it. Will make sure I push a fix today and make sure it’s also up to date

ornate cypress
split iron
#

hi @last echo - I just pushed the changes to the example agent so it works now (https://github.com/jasonmccallister/laravel-assistant). However, I need to update the readme and record a video walkthrough so its makes more sense. Apologies for the confusion. I'll let you know when the readme and videos are up