#I've been working on the blueprint
1 messages Β· Page 1 of 1 (latest)
Iβm picking up a wedding suit atm but will be back at 2pm PT to help sync
Otherwise happy to help async
No rush, thanks! Kind of hoping that you'll be wearing the wedding suit while helping me π
Im trying to coax Zed+Claude into figuring it out
I'm around now!
sorry was afk.. let me share a few details in case it rings a bell! thanks!
@honest pebble just pushed the draft PR https://github.com/dagger/dagger/pull/10712
basically you can do eg.
dagger init --blueprint=github.com/shykes/x/go
# load functions from the blueprint module...
dagger functions
# ... but execute them in the context of the current module
dagger call build
But there's a problem when loading the module. You can repro with:
dagger -m github.com/shykes/dagger@module-blueprint <<.
dev |
with-exec -- dagger init --blueprint=github.com/shykes/x/go |
with-exec dagger functions |
stdout
.
dagger functions fails with:
Error: main object not found, check that your module's name and main object match
It makes sense that there would be issues related to the module name: when loading a module that references a blueprint, you get the types from one module, and the name from the other. That's probably where the mismatch comes from, I think?
I looked at the PR and the issue! Pretty cool but isnβt it very similar to interface support in the way itβs implemented right now?
Yeah, you can actually avoid it by running this instead:
dagger -m github.com/shykes/dagger@module-blueprint <<.
dev |
with-exec -- dagger init --blueprint=github.com/shykes/x/go --name=go |
with-exec dagger functions |
stdout
.
(diff being the additional --name=go)
The CLI is looking for an object with the same name as the module itself. Since in your failing example you are getting the default module name (happens to be mnt in this case cause that is the name of the dir you are in), it's looking for an object named Mnt but can't find it and errors out. That's why specifying --name=go avoids the error; there now is an object named Go which gets found.
If I'm understanding the proposal in https://github.com/dagger/dagger/issues/10464 correctly, I guess that the solution might be as simple as automatically naming the new module the same as the blueprint?
If we don't want that restriction for whatever reason, we could most likely update the CLI to handle this case where there's a blueprint and look for an object with the name of the blueprint rather than the name of the module in that particular case
Ideally it would be the other way around: the downstream module keeps its name, and we fix loading such that the main object is named correctly.
(otherwise it would be weird, imagine 50 dagger modules for 50 go apps, using a blueprint module called "go", and all 50 modules are called "go")
OK I changed the target module name to the blueprint name as a workaround.. works fine... but... there was a worse bug hiding.
Functions are still executed in the context dir of the upstream blueprint module π
I could use some guidance on the correct hook points here... Claude was very confident but... it seems that it was wrong
Poking around but no idea how to solve it
@honest pebble any chance I can bug you for a few minutes after the demo call? π I'd really like to get the PR ready for review before the week-end
Yep I'm looking at the PR right now, trying locally to see if I can track down why it's picking up the wrong context dir
Suspect it's because the blueprint is a git module and the code that does the actual contextual dir loads will just go look at the git context dir to load files: https://github.com/sipsma/dagger/blob/e035126279e30913831033156f0b9d544873f896/core/modulesource.go#L354-L354
Seeing what's possible in terms of fixing
BTW I've been thinking about the module name question from before... I think having the blueprint name used everywhere might have undesirable consequences, like for example telemetry might show everything under the blueprint's module name, so if 100 modules use a given module, all the telemetry from running those 100 modules will show as the blueprint running it instead.
(but still a less urgent problem than the context dir one)
This fixes it:
diff --git a/core/modfunc.go b/core/modfunc.go
index 662517d44..8543c284e 100644
--- a/core/modfunc.go
+++ b/core/modfunc.go
@@ -635,7 +635,7 @@ func (fn *ModuleFunction) loadContextualArg(
case "Directory":
slog.Debug("moduleFunction.loadContextualArg: loading contextual directory", "fn", arg.Name, "dir", arg.DefaultPath)
- dir, err := fn.mod.Source.Self().LoadContext(ctx, dag, arg.DefaultPath, arg.Ignore)
+ dir, err := fn.mod.ContextSource.Self().LoadContext(ctx, dag, arg.DefaultPath, arg.Ignore)
if err != nil {
return nil, fmt.Errorf("failed to load contextual directory %q: %w", arg.DefaultPath, err)
}
@@ -649,7 +649,7 @@ func (fn *ModuleFunction) loadContextualArg(
filePath := filepath.Base(arg.DefaultPath)
// Load the directory containing the file.
- dir, err := fn.mod.Source.Self().LoadContext(ctx, dag, dirPath, nil)
+ dir, err := fn.mod.ContextSource.Self().LoadContext(ctx, dag, dirPath, nil)
if err != nil {
return nil, fmt.Errorf("failed to load contextual directory %q: %w", dirPath, err)
}
diff --git a/core/module.go b/core/module.go
index 4548aeb6c..961dc1973 100644
--- a/core/module.go
+++ b/core/module.go
@@ -22,6 +22,9 @@ type Module struct {
// The source of the module
Source dagql.ObjectResult[*ModuleSource] `field:"true" name:"source" doc:"The source for the module."`
+ // The source to load contextual dirs/files from, which may be different than Source for blueprints
+ ContextSource dagql.ObjectResult[*ModuleSource]
+
// The name of the module
NameField string `field:"true" name:"name" doc:"The name of the module"`
diff --git a/core/schema/modulesource.go b/core/schema/modulesource.go
index ed4166f56..4ee4e3d0d 100644
--- a/core/schema/modulesource.go
+++ b/core/schema/modulesource.go
@@ -2241,13 +2241,12 @@ func (s *moduleSourceSchema) moduleSourceAsModule(
var blueprintSrc dagql.ObjectResult[*core.ModuleSource]
var targetName string
var targetOriginalName string
- var targetContextDir dagql.ObjectResult[*core.Directory]
+ originalSrc := src
if src.Self().Blueprint.Self() != nil {
// Store target module information
targetName = src.Self().ModuleName
targetOriginalName = src.Self().ModuleOriginalName
- targetContextDir = src.Self().ContextDirectory
// Use blueprint for SDK operations
blueprintSrc = src.Self().Blueprint
@@ -2261,7 +2260,8 @@ func (s *moduleSourceSchema) moduleSourceAsModule(
// Create module with blueprint source for SDK operations
mod := &core.Module{
- Source: src,
+ Source: src,
+ ContextSource: originalSrc,
NameField: src.Self().ModuleName,
OriginalName: src.Self().ModuleOriginalName,
@@ -2322,7 +2322,6 @@ func (s *moduleSourceSchema) moduleSourceAsModule(
// If using a blueprint, restore target context and name for file operations
if blueprintSrc.Self() != nil {
- mod.Source.Self().ContextDirectory = targetContextDir
mod.NameField = targetName
mod.OriginalName = targetOriginalName
// Use the target's module name for the final result
Basically just track which source to load context from separately. @errant locust you good with me just pushing that to the PR?
yes please!
Yeah the telemetry problem occurred to me while looking through this too. Worst case can just special case the module telemetry to handle blueprint modules (relevant code), but I'll think whether there's any better more general way of modeling this. It would be nice if the ModuleSource for the Module was unaltered and it just ended up with Runtime/Schema from the blueprint source
the worst part is that I think Claude correctly made a plan to do this, but then just... didn't
Honestly its attempt was reasonable on a superficial level, it just missed some relevant details
I don't think there's many "strongly-typed DAG execution engines" in its training data π It oscillates between brilliance and bone-headedness when I use it on the engine codebase
pushed
@honest pebble do you think there's an easy fix for the name thing?
The name that's presented to callers should just be mapped from "underlying blueprint name" -> "wrapped name". There's needs to be a translation layer internally though because the module runtime needs to know what's actually being invoked.
This feels very similar to the existing support for renaming a dependency, I need to refresh my memory on how/where that happens though. I'll check and see if we can just re-use that
I was naively thinking: if I change the module's name, I can also just rename that module's main module, and everything should still work...
When the blueprint is invoked, its Runtime container given the name of the object and the function on it to call. If the main object has some unexpected name, then trying to invoke functions on it will confuse the runtime code. That's the only problem I can think of that needs to be avoided
confirming that your fix works! 
I'll push my own last little fix with the name override, then open the PR for real
thank you π
Yeah looking at the code, what important is that the final Module.OriginalName stays as the blueprint module's name (so go for the examples). But you could change the Module.Name to be the "wrapper" one and then all the API schema names + telemetry should work afaict
Oh! interesting
This is because OriginalName is what the CLI introspection happens to use?
Oh, I'll need to change dagger update so that it also updates the blueprint
(either that or I remove the pinning feature for the blueprint... but that seems like a more controversial change)
Sort of the opposite actually. OriginalName is mostly only used internally and handles the case where the name presented to callers differs from what the module think its name is. The Name is what's presented to callers and OriginalName is used internally when actually invoking the runtime.
So as long as Name is what you want presented (i.e. the name of the wrapper module) and OriginalName is the real underlying blueprint name, it should work (π€)
dagger core module-source --ref-string . as-module name
probably the most direct way
Oh there's also the prompt in the shell! It works π
OK everything seems to work. Thanks again
no problem, happy to help!