Skip to content

feat(slides): add insert-image to place a sized image on an existing slide#695

Merged
steipete merged 6 commits into
openclaw:mainfrom
Czaruno:feat/slides-insert-image
Jun 7, 2026
Merged

feat(slides): add insert-image to place a sized image on an existing slide#695
steipete merged 6 commits into
openclaw:mainfrom
Czaruno:feat/slides-insert-image

Conversation

@Czaruno
Copy link
Copy Markdown
Contributor

@Czaruno Czaruno commented Jun 5, 2026

What

Adds gog slides insert-image: place a positioned, sized image on an existing slide.

add-slide is great for full-bleed image slides, but there's no way to drop a sized image (a logo top-right, a chart in a content area) onto a slide you already have. The Slides REST createImage only accepts a publicly-fetchable URL, so callers otherwise have to hand-roll the upload + temporary public permission + createImage + cleanup, or make files public by hand.

This reuses the exact private-image flow add-slide/replace-slide already use, so nothing is left public:

  1. Upload the image to Drive as a temp file.
  2. Grant a temporary anyone: reader permission so the Slides image fetcher can read it.
  3. createImage onto the target slide with explicit size + transform.
  4. Delete the temp Drive file (defer).

Usage

gog slides insert-image <presentationId> <slideId> <image> \
  --x=<n> --y=<n> --width=<n> [--height=<n>] [--unit=PT|EMU]
  • Args: presentationId, slideId, image (PNG/JPG/GIF).
  • --width is required; --height is optional and derived from the image's aspect ratio when omitted.
  • --unit defaults to PT.
  • Confirms the target slide exists before uploading anything.

Testing

  • go build ./..., go vet ./internal/cmd/ clean.
  • New unit tests (httptest-mocked Drive + Slides, mirroring slides_add_slide_test.go):
    • places the image on the target slide with the expected size/transform, sets the temp permission, and deletes the temp file;
    • rejects a missing slide before any Drive call;
    • aspect-ratio derivation.
  • Existing ./internal/cmd tests still pass.
  • Verified live end to end against a real presentation: inserted a 120pt square logo at the top-right of an existing slide and confirmed placement via the rendered thumbnail.

Notes

  • No new module dependencies (stdlib image for aspect detection).
  • Per-command docs under docs/commands/ can be regenerated by the maintainers' doc tooling.

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented Jun 5, 2026

Codex review: found issues before merge. Reviewed June 7, 2026, 4:46 PM ET / 20:46 UTC.

Summary
The PR adds gog slides insert-image with positioned, sized local-image insertion on an existing slide, generated command docs, unit tests, and a changelog entry.

Reproducibility: not applicable. this is a feature PR rather than a bug report. The PR discussion includes redacted live terminal proof plus mocked tests for the new command behavior.

Review metrics: 2 noteworthy metrics.

  • Diff surface: 8 files changed, +533/-1. The PR is focused but adds a new command, implementation, tests, generated docs, and release-note text.
  • Public sharing paths: 1 new anyone reader flow. The new Drive permission path is the security-boundary decision that unit tests cannot settle.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🦞 diamond lobster
Patch quality: 🦐 gold shrimp
Result: needs maintainer review before merge.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Add a finite timeout around the cancellation-immune Drive cleanup delete.
  • Get maintainer acceptance or requested adjustment for the temporary public Drive sharing policy.

Risk before merge

  • [P1] The new command temporarily grants anyone reader access to a user-provided local image; maintainers need to accept that Slides policy or require explicit consent.
  • [P2] The cleanup delete uses a cancellation-immune context without a timeout, so a stalled Drive request can hang the command after insertion and leave the temporary public upload exposed longer.

Maintainer options:

  1. Bound cleanup before merge (recommended)
    Wrap the cancellation-immune Drive delete in a finite timeout and keep the stderr warning so cleanup cannot hang indefinitely.
  2. Accept the Slides sharing pattern
    Maintainers can explicitly allow insert-image to follow add-slide and replace-slide once the cleanup path is bounded.
  3. Require explicit public-share consent
    If Slides should follow the Docs policy instead, ask for a prompt or opt-in path before granting temporary anyone reader access.

Next step before merge

  • [P2] The author can make the cleanup timeout repair, but maintainers still need to decide whether this new command should use the temporary public Drive-sharing policy by default.

Security
Needs attention: The diff introduces a new temporary public Drive sharing path, and its cleanup needs a timeout before the security boundary is comfortable to merge.

Review findings

  • [P2] Bound the cleanup delete context — internal/cmd/slides_insert_image.go:141
Review details

Best possible solution:

Land the focused command after bounding cleanup and after maintainers explicitly choose the intended temporary-public-sharing policy for Slides image commands.

Do we have a high-confidence way to reproduce the issue?

Not applicable; this is a feature PR rather than a bug report. The PR discussion includes redacted live terminal proof plus mocked tests for the new command behavior.

Is this the best way to solve the issue?

Unclear; the implementation is narrow and proof-positive, but it is not the best merge state until cleanup is bounded and maintainers accept or adjust the temporary public-sharing policy.

Full review comments:

  • [P2] Bound the cleanup delete context — internal/cmd/slides_insert_image.go:141
    The cleanup defer deletes the temporary public Drive file with context.WithoutCancel(ctx) but no timeout. If that Drive delete request stalls, Run can hang after creating the image while the anyone-readable upload remains public longer; wrap the uncancelled cleanup context in a finite timeout and cancel it.
    Confidence: 0.87

Overall correctness: patch is incorrect
Overall confidence: 0.87

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 7256355c7fc8.

Label changes

Label justifications:

  • P2: This is a normal-priority user-facing Slides feature with bounded scope but nontrivial merge review needs.
  • merge-risk: 🚨 security-boundary: The diff adds a new command path that temporarily grants public read access to a user-provided Drive upload.
  • merge-risk: 🚨 availability: The cleanup delete uses a cancellation-immune context without a timeout, so a stalled Drive request can hang the command after insertion.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (terminal): The PR discussion includes redacted terminal proof for dry-run, a real insert run, read-slide confirmation, and temp-upload deletion verification.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR discussion includes redacted terminal proof for dry-run, a real insert run, read-slide confirmation, and temp-upload deletion verification.
Evidence reviewed

Security concerns:

  • [medium] New temporary public Drive permission path — internal/cmd/slides_insert_image.go:147
    The command grants anyone reader access to an uploaded local image so Google Slides can fetch it; this is intentional but expands a security boundary that maintainers need to accept or align with the Docs confirmation behavior.
    Confidence: 0.88
  • [medium] Unbounded cleanup request — internal/cmd/slides_insert_image.go:141
    The deletion uses context.WithoutCancel(ctx) without a timeout, so a stalled cleanup request can hang the command and prolong public exposure of the temporary upload.
    Confidence: 0.86

Acceptance criteria:

  • [P1] go test ./internal/cmd -run 'TestSlidesInsertImage|TestImageAspectRatio' -v.
  • [P1] go vet ./internal/cmd.

What I checked:

Likely related people:

  • steipete: Recent main-history commits touched Slides image URL handling and related Docs image cleanup behavior, and this PR branch also has maintainer follow-up commits for changelog, lint, and generated docs. (role: recent area contributor; confidence: high; commits: c11876a7e9b8, b980fe7d3d94, 3bed2b06e788; files: internal/cmd/slides_add_slide.go, internal/cmd/slides_replace_slide.go, internal/cmd/docs_insert_image.go)
  • chrismdp: The original merged Slides command bundle added add-slide, read-slide, update-notes, and replace-slide, including the image-deck workflow this PR extends. (role: introduced related Slides behavior; confidence: medium; commits: 8b08d11777fe; files: internal/cmd/slides.go, internal/cmd/slides_add_slide.go, internal/cmd/slides_replace_slide.go)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. labels Jun 5, 2026
@Czaruno
Copy link
Copy Markdown
Contributor Author

Czaruno commented Jun 5, 2026

Thanks for the review. Addressed both P1 findings and added the requested behavior proof.

Changes (commit on this branch)

  • Drive setup ordering: the target slide is now validated before the Drive service is created or anything is uploaded, so a bad slide id never touches Drive. The missing-slide test now asserts Drive is never called.
  • Checked cleanup of the temporary public image: the temp file is deleted via a cancellation-immune context (context.WithoutCancel), and a failed delete now logs a loud Warning: to stderr instead of being swallowed (a failed cleanup could otherwise leave the upload world-readable). Added a cleanup-failure test asserting the warning fires.

Tests

$ go build ./...        # clean
$ go vet ./internal/cmd # clean
$ go test ./internal/cmd -run 'TestSlidesInsertImage|TestImageAspectRatio' -v
--- PASS: TestSlidesInsertImage_PlacesSizedImageOnExistingSlide
--- PASS: TestSlidesInsertImage_RejectsMissingSlide
--- PASS: TestSlidesInsertImage_WarnsWhenCleanupFails
--- PASS: TestImageAspectRatio
ok  github.com/steipete/gogcli/internal/cmd

Live behavior proof

Run against a real (now-deleted) scratch presentation, account redacted. A neutral 300x150 (2:1) PNG was used; note --height is omitted and auto-derived from the aspect ratio.

# dry-run shows the computed request (width 100 -> height 50 from the 2:1 image)
$ gog slides insert-image <PID> p /tmp/insimg_test.png --x=560 --y=24 --width=100 --dry-run -p
dry_run        true
op             slides.insert-image
request_json   {"height":50,"image":"/tmp/insimg_test.png","mime_type":"image/png",
                "presentation_id":"<PID>","slide_id":"p","unit":"PT","width":100,"x":560,"y":24}

# real run
$ gog slides insert-image <PID> p /tmp/insimg_test.png --x=560 --y=24 --width=100 -j
{
  "imageObjectId": "img_1780625295086419000",
  "slideObjectId": "p",
  "presentationId": "<PID>",
  "link": "https://docs.google.com/presentation/d/<PID>/edit"
}

# read-slide confirms the image element is now on the existing slide
$ gog slides read-slide <PID> p -p
Slide 1  (p)
Images:
OBJECT ID                URL
img_1780625295086419000  https://lh7-rt.googleusercontent.com/slidesz/AGV_vU...=s2048  (rendered, redacted)

The temporary Drive upload was deleted automatically after insertion (verified separately; a subsequent Drive listing shows no residual file).

@clawsweeper re-review

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented Jun 5, 2026

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 5, 2026
@Czaruno
Copy link
Copy Markdown
Contributor Author

Czaruno commented Jun 5, 2026

Fixed the test-isolation nit: TestSlidesInsertImage_RejectsMissingSlide now saves and restores the package-global newDriveService in its cleanup (alongside newSlidesService). Full go test ./internal/cmd passes. That clears the only code finding; the remaining item is the maintainer call on the temporary public-Drive pattern, which matches the existing add-slide/replace-slide flow and now warns on cleanup failure.

@clawsweeper re-review

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented Jun 5, 2026

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Jun 5, 2026
Czaruno and others added 5 commits June 7, 2026 21:16
…slide

add-slide only lays a full-bleed image on a new slide. insert-image places
a positioned, sized image on an existing slide, reusing the same private-image
flow as add-slide: upload to Drive, grant a temporary anyone-reader permission
so the Slides image fetcher can read it, createImage, then delete the temp file.

- Args: presentationId, slideId, image (PNG/JPG/GIF).
- Flags: --x, --y, --width (required), --height, --unit (PT|EMU, default PT).
- --height is optional: derived from the image's aspect ratio when omitted.
- Confirms the target slide exists before uploading anything.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ge cleanup failures

Address review feedback on insert-image:
- Create the Drive service and upload only after confirming the target slide
  exists, so a bad slide id never touches Drive.
- Delete the temporary public image via a cancellation-immune context and log a
  loud warning if deletion fails, instead of swallowing the error (a failed
  cleanup could otherwise leave the upload world-readable until manual removal).
- Add a cleanup-failure test asserting the warning is emitted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…slide test

The missing-slide test overrode the package-global newDriveService without
restoring it, leaking the stub into later tests. Save and restore it in the
cleanup alongside newSlidesService.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@steipete steipete force-pushed the feat/slides-insert-image branch from ba70530 to 31a0c11 Compare June 7, 2026 20:30
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jun 7, 2026
@steipete steipete merged commit bedfa7d into openclaw:main Jun 7, 2026
7 checks passed
@steipete
Copy link
Copy Markdown
Collaborator

steipete commented Jun 7, 2026

Landed in bedfa7d.

Thanks @Czaruno. I accepted the temporary public Drive read handoff for this command so Slides can fetch the uploaded local image, with cleanup warning coverage if deletion fails.

Proof:

  • go test ./internal/cmd -run 'TestSlidesInsertImage|TestImageAspectRatio'
  • make lint
  • make ci
  • autoreview --mode branch --base origin/main: clean, no accepted/actionable findings
  • GitHub Actions on 072e1bf: ci test/windows/darwin-cgo-build/worker passed; docker image passed; Socket checks passed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants