Skip to content

Commit 5d5352d

Browse files
committed
enhance: add ability to get revision ID when opening file in a workspace
Signed-off-by: Donnie Adams <[email protected]>
1 parent 834896a commit 5d5352d

File tree

5 files changed

+178
-87
lines changed

5 files changed

+178
-87
lines changed

go.mod

+7-6
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@ module github.com/gptscript-ai/go-gptscript
33
go 1.23.0
44

55
require (
6-
github.com/getkin/kin-openapi v0.124.0
7-
github.com/stretchr/testify v1.8.4
6+
github.com/getkin/kin-openapi v0.129.0
7+
github.com/stretchr/testify v1.10.0
88
)
99

1010
require (
1111
github.com/davecgh/go-spew v1.1.1 // indirect
12-
github.com/go-openapi/jsonpointer v0.20.2 // indirect
13-
github.com/go-openapi/swag v0.22.8 // indirect
14-
github.com/invopop/yaml v0.2.0 // indirect
12+
github.com/go-openapi/jsonpointer v0.21.0 // indirect
13+
github.com/go-openapi/swag v0.23.0 // indirect
1514
github.com/josharian/intern v1.0.0 // indirect
16-
github.com/mailru/easyjson v0.7.7 // indirect
15+
github.com/mailru/easyjson v0.9.0 // indirect
1716
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
17+
github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80 // indirect
18+
github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349 // indirect
1819
github.com/perimeterx/marshmallow v1.1.5 // indirect
1920
github.com/pmezard/go-difflib v1.0.0 // indirect
2021
gopkg.in/yaml.v3 v3.0.1 // indirect

go.sum

+14-13
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,39 @@
11
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
22
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3-
github.com/getkin/kin-openapi v0.124.0 h1:VSFNMB9C9rTKBnQ/fpyDU8ytMTr4dWI9QovSKj9kz/M=
4-
github.com/getkin/kin-openapi v0.124.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
5-
github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
6-
github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
7-
github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw=
8-
github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI=
3+
github.com/getkin/kin-openapi v0.129.0 h1:QGYTNcmyP5X0AtFQ2Dkou9DGBJsUETeLH9rFrJXZh30=
4+
github.com/getkin/kin-openapi v0.129.0/go.mod h1:gmWI+b/J45xqpyK5wJmRRZse5wefA5H0RDMK46kLUtI=
5+
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
6+
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
7+
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
8+
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
99
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
1010
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
11-
github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
12-
github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
1311
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
1412
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
1513
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
1614
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
1715
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
1816
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
19-
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
20-
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
17+
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
18+
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
2119
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
2220
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
21+
github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80 h1:nZspmSkneBbtxU9TopEAE0CY+SBJLxO8LPUlw2vG4pU=
22+
github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80/go.mod h1:7tFDb+Y51LcDpn26GccuUgQXUk6t0CXZsivKjyimYX8=
23+
github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349 h1:t05Ww3DxZutOqbMN+7OIuqDwXbhl32HiZGpLy26BAPc=
24+
github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o=
2325
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
2426
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
2527
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
2628
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
2729
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
2830
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
29-
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
30-
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
31+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
32+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
3133
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
3234
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
3335
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
3436
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
3537
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
36-
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
3738
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
3839
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

gptscript_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func TestMain(m *testing.M) {
3030
panic(fmt.Sprintf("error creating gptscript: %s", err))
3131
}
3232

33-
g, err = NewGPTScript(GlobalOptions{OpenAIAPIKey: os.Getenv("OPENAI_API_KEY")})
33+
g, err = NewGPTScript(GlobalOptions{OpenAIAPIKey: os.Getenv("OPENAI_API_KEY"), WorkspaceTool: "/Users/thedadams/code/workspace-provider"})
3434
if err != nil {
3535
gFirst.Close()
3636
panic(fmt.Sprintf("error creating gptscript: %s", err))

workspace.go

+44-31
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,9 @@ func (g *GPTScript) RemoveAll(ctx context.Context, opts ...RemoveAllOptions) err
147147
}
148148

149149
type WriteFileInWorkspaceOptions struct {
150-
WorkspaceID string
151-
CreateRevision *bool
152-
LatestRevision string
150+
WorkspaceID string
151+
CreateRevision *bool
152+
LatestRevisionID string
153153
}
154154

155155
func (g *GPTScript) WriteFileInWorkspace(ctx context.Context, filePath string, contents []byte, opts ...WriteFileInWorkspaceOptions) error {
@@ -161,8 +161,8 @@ func (g *GPTScript) WriteFileInWorkspace(ctx context.Context, filePath string, c
161161
if o.CreateRevision != nil {
162162
opt.CreateRevision = o.CreateRevision
163163
}
164-
if o.LatestRevision != "" {
165-
opt.LatestRevision = o.LatestRevision
164+
if o.LatestRevisionID != "" {
165+
opt.LatestRevisionID = o.LatestRevisionID
166166
}
167167
}
168168

@@ -171,13 +171,13 @@ func (g *GPTScript) WriteFileInWorkspace(ctx context.Context, filePath string, c
171171
}
172172

173173
_, err := g.runBasicCommand(ctx, "workspaces/write-file", map[string]any{
174-
"id": opt.WorkspaceID,
175-
"contents": base64.StdEncoding.EncodeToString(contents),
176-
"filePath": filePath,
177-
"createRevision": opt.CreateRevision,
178-
"latestRevision": opt.LatestRevision,
179-
"workspaceTool": g.globalOpts.WorkspaceTool,
180-
"env": g.globalOpts.Env,
174+
"id": opt.WorkspaceID,
175+
"contents": base64.StdEncoding.EncodeToString(contents),
176+
"filePath": filePath,
177+
"createRevision": opt.CreateRevision,
178+
"latestRevisionID": opt.LatestRevisionID,
179+
"workspaceTool": g.globalOpts.WorkspaceTool,
180+
"env": g.globalOpts.Env,
181181
})
182182

183183
return parsePossibleConflictInWorkspaceError(err)
@@ -214,26 +214,34 @@ func (g *GPTScript) DeleteFileInWorkspace(ctx context.Context, filePath string,
214214
}
215215

216216
type ReadFileInWorkspaceOptions struct {
217-
WorkspaceID string
217+
WorkspaceID string
218+
WithLatestRevisionID bool
218219
}
219220

220-
func (g *GPTScript) ReadFileInWorkspace(ctx context.Context, filePath string, opts ...ReadFileInWorkspaceOptions) ([]byte, error) {
221+
type ReadFileInWorkspaceResponse struct {
222+
Content []byte `json:"content"`
223+
RevisionID string `json:"revisionID"`
224+
}
225+
226+
func (g *GPTScript) ReadFileInWorkspace(ctx context.Context, filePath string, opts ...ReadFileInWorkspaceOptions) (*ReadFileInWorkspaceResponse, error) {
221227
var opt ReadFileInWorkspaceOptions
222228
for _, o := range opts {
223229
if o.WorkspaceID != "" {
224230
opt.WorkspaceID = o.WorkspaceID
225231
}
232+
opt.WithLatestRevisionID = opt.WithLatestRevisionID || o.WithLatestRevisionID
226233
}
227234

228235
if opt.WorkspaceID == "" {
229236
opt.WorkspaceID = os.Getenv("GPTSCRIPT_WORKSPACE_ID")
230237
}
231238

232239
out, err := g.runBasicCommand(ctx, "workspaces/read-file", map[string]any{
233-
"id": opt.WorkspaceID,
234-
"filePath": filePath,
235-
"workspaceTool": g.globalOpts.WorkspaceTool,
236-
"env": g.globalOpts.Env,
240+
"id": opt.WorkspaceID,
241+
"filePath": filePath,
242+
"withLatestRevisionID": opt.WithLatestRevisionID,
243+
"workspaceTool": g.globalOpts.WorkspaceTool,
244+
"env": g.globalOpts.Env,
237245
})
238246
if err != nil {
239247
if strings.HasSuffix(err.Error(), fmt.Sprintf("not found: %s/%s", opt.WorkspaceID, filePath)) {
@@ -242,7 +250,13 @@ func (g *GPTScript) ReadFileInWorkspace(ctx context.Context, filePath string, op
242250
return nil, err
243251
}
244252

245-
return base64.StdEncoding.DecodeString(out)
253+
var resp ReadFileInWorkspaceResponse
254+
err = json.Unmarshal([]byte(out), &resp)
255+
if err != nil {
256+
return nil, err
257+
}
258+
259+
return &resp, nil
246260
}
247261

248262
type FileInfo struct {
@@ -251,10 +265,12 @@ type FileInfo struct {
251265
Size int64
252266
ModTime time.Time
253267
MimeType string
268+
RevisionID string
254269
}
255270

256271
type StatFileInWorkspaceOptions struct {
257-
WorkspaceID string
272+
WorkspaceID string
273+
WithLatestRevisionID bool
258274
}
259275

260276
func (g *GPTScript) StatFileInWorkspace(ctx context.Context, filePath string, opts ...StatFileInWorkspaceOptions) (FileInfo, error) {
@@ -263,17 +279,19 @@ func (g *GPTScript) StatFileInWorkspace(ctx context.Context, filePath string, op
263279
if o.WorkspaceID != "" {
264280
opt.WorkspaceID = o.WorkspaceID
265281
}
282+
opt.WithLatestRevisionID = opt.WithLatestRevisionID || o.WithLatestRevisionID
266283
}
267284

268285
if opt.WorkspaceID == "" {
269286
opt.WorkspaceID = os.Getenv("GPTSCRIPT_WORKSPACE_ID")
270287
}
271288

272289
out, err := g.runBasicCommand(ctx, "workspaces/stat-file", map[string]any{
273-
"id": opt.WorkspaceID,
274-
"filePath": filePath,
275-
"workspaceTool": g.globalOpts.WorkspaceTool,
276-
"env": g.globalOpts.Env,
290+
"id": opt.WorkspaceID,
291+
"filePath": filePath,
292+
"withLatestRevisionID": opt.WithLatestRevisionID,
293+
"workspaceTool": g.globalOpts.WorkspaceTool,
294+
"env": g.globalOpts.Env,
277295
})
278296
if err != nil {
279297
if strings.HasSuffix(err.Error(), fmt.Sprintf("not found: %s/%s", opt.WorkspaceID, filePath)) {
@@ -291,16 +309,11 @@ func (g *GPTScript) StatFileInWorkspace(ctx context.Context, filePath string, op
291309
return info, nil
292310
}
293311

294-
type RevisionInfo struct {
295-
FileInfo
296-
RevisionID string
297-
}
298-
299312
type ListRevisionsForFileInWorkspaceOptions struct {
300313
WorkspaceID string
301314
}
302315

303-
func (g *GPTScript) ListRevisionsForFileInWorkspace(ctx context.Context, filePath string, opts ...ListRevisionsForFileInWorkspaceOptions) ([]RevisionInfo, error) {
316+
func (g *GPTScript) ListRevisionsForFileInWorkspace(ctx context.Context, filePath string, opts ...ListRevisionsForFileInWorkspaceOptions) ([]FileInfo, error) {
304317
var opt ListRevisionsForFileInWorkspaceOptions
305318
for _, o := range opts {
306319
if o.WorkspaceID != "" {
@@ -325,7 +338,7 @@ func (g *GPTScript) ListRevisionsForFileInWorkspace(ctx context.Context, filePat
325338
return nil, err
326339
}
327340

328-
var info []RevisionInfo
341+
var info []FileInfo
329342
err = json.Unmarshal([]byte(out), &info)
330343
if err != nil {
331344
return nil, err

0 commit comments

Comments
 (0)