Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions backend/biz/agentresource/noop_objectstore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package agentresource

import (
"context"
"errors"
"fmt"
"io"
"time"
)

// noopObjectStore is used when ObjectStorage is disabled in config. Every
// fetch fails with a stable sentinel-ish error so resolver-level warn logs
// stay informative ("skill skipped: object storage disabled") rather than
// crashing with a nil deref.
type noopObjectStore struct{}

func (noopObjectStore) GetObject(_ context.Context, _ string) (io.ReadCloser, error) {
return nil, fmt.Errorf("object storage disabled")
}

func (noopObjectStore) PresignGet(_ context.Context, _ string, _ time.Duration) (string, error) {
return "", errors.New("object storage disabled")
}
77 changes: 77 additions & 0 deletions backend/biz/agentresource/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Package agentresource — DI wiring for the agent-resource read-only stack.
//
// The Repo / Resolver pair is consumed by:
// - biz/task/usecase (rule + skill + plugin injection into ConfigFile slice)
// - biz/skill/handler/v1 (/api/v1/skills picker)
// - biz/plugin/handler/v1 (/api/v1/plugins picker)
package agentresource

import (
"context"
"log/slog"

"github.com/samber/do"

"github.com/chaitin/MonkeyCode/backend/config"
"github.com/chaitin/MonkeyCode/backend/db"
"github.com/chaitin/MonkeyCode/backend/pkg/oss"
)

// ProvideAgentResource wires the agent-resource module. The ObjectStore is
// picked from whichever bucket block is configured:
//
// - object_storage.enabled = true → AWS-SDK-v2 client (any S3-compatible
// store: MinIO, RustFS, real AWS). Reuses the same client avatar / repo /
// spec / temp uploads use, so single SDK in the binary.
// - aliyun.public_oss.bucket set → aliyun-oss-go-sdk client. AWS SDK's
// SigV4 signer is incompatible with Aliyun OSS (SignatureDoesNotMatch +
// bucket double-prefix in path-style URLs), so we wire a native client
// just for this code path. Existing pkg/oss.Client is untouched; avatar
// etc. still go through the AWS SDK path when object_storage is on.
// - neither configured → nil ObjectStore. Resolver downgrades
// to noopObjectStore; fetch/presign each fail and the per-asset skip
// pipeline keeps the task creating without rule/skill/plugin assets.
func ProvideAgentResource(i *do.Injector) {
do.Provide(i, func(i *do.Injector) (Repo, error) {
return NewRepo(do.MustInvoke[*db.Client](i)), nil
})

do.Provide(i, func(i *do.Injector) (ObjectStore, error) {
cfg := do.MustInvoke[*config.Config](i)
logger := do.MustInvoke[*slog.Logger](i)

// Primary: ObjectStorage block — AWS-SDK-v2 client.
if cfg.ObjectStorage.Enabled {
opt := oss.S3Option{
ForcePathStyle: cfg.ObjectStorage.ForcePathStyle,
InitBucket: cfg.ObjectStorage.InitBucket,
}
client, err := oss.NewS3Compatible(context.Background(), cfg.ObjectStorage, opt)
if err != nil {
return nil, err
}
return client, nil
}

// Fallback: aliyun.public_oss — native aliyun-oss-go-sdk client.
if pub := cfg.Aliyun.PublicOSS; pub.Bucket != "" && pub.Endpoint != "" {
logger.Info("agentresource: using aliyun.public_oss (native SDK)",
"endpoint", pub.Endpoint, "bucket", pub.Bucket)
client, err := oss.NewAliyunOSS(pub)
if err != nil {
return nil, err
}
return client, nil
}

// Neither block configured — Resolver downgrades to noopObjectStore.
return noopObjectStore{}, nil
})

do.Provide(i, func(i *do.Injector) (ResolverInterface, error) {
repo := do.MustInvoke[Repo](i)
store := do.MustInvoke[ObjectStore](i)
logger := do.MustInvoke[*slog.Logger](i)
return NewResolver(repo, store, logger), nil
})
}
Loading