Skip to content

[NOT-650] Add profile duplication command - #53

Draft
leo-notte wants to merge 2 commits into
mainfrom
feat/profile-duplication
Draft

[NOT-650] Add profile duplication command#53
leo-notte wants to merge 2 commits into
mainfrom
feat/profile-duplication

Conversation

@leo-notte

@leo-notte leo-notte commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add notte profiles duplicate --profile-id <id>
  • accept an optional --name
  • use the authenticated API client transport
  • cover method, path, payload, and output

Companion to nottelabs/monorepo#1918.

Linear: NOT-650 https://linear.app/nottelabsinc/issue/NOT-650/notte-cli-pr-53-add-profile-duplication-command

@greptile-apps

greptile-apps Bot commented Jul 27, 2026

Copy link
Copy Markdown

Greptile Summary

Adds profile duplication support:

  • Registers notte profiles duplicate with required --profile-id and optional --name flags.
  • Sends the duplication request through the authenticated API client transport and formats the returned profile.
  • Adds a unit test covering the request method, path, payload, and command output.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
internal/cmd/profiles.go Adds and registers the profile duplication command, builds its authenticated POST request, handles API errors, and prints the duplicated profile.
internal/cmd/profiles_test.go Adds focused coverage for the duplicate command's HTTP method, endpoint, optional name payload, and rendered profile output.

Reviews (3): Last reviewed commit: "feat: add profile duplication command" | Re-trigger Greptile

@giordano-lucas giordano-lucas changed the title Add profile duplication command [NOT-650] Add profile duplication command Jul 28, 2026
giordano-lucas added a commit that referenced this pull request Aug 31, 2026
The manifest #85 introduced listed five endpoints as "not exposed yet". Four of
them are worth having, so they are commands now and the skip lines are gone -
which is the file working as intended, as a list of decisions to revisit rather
than a place gaps go to be forgotten. `profiles duplicate` stays listed: it is
already proposed in #53.

  notte personas update --persona-id <id> --name ...
  notte profiles cookies --profile-id <id>
  notte profiles cookies-set --profile-id <id> --file cookies.json
  notte usage logs [--endpoint ...] [--page N] [--page-size N]

`personas update` is generated: PATCH /personas/{persona_id} is a JSON body
behind a $ref, so it needed an endpointMap entry and nothing else.

`profiles cookies-set` accepts either shape a cookies file comes in - a bare
array, which is what Playwright's storageState and the browser extensions
write, or an object with a `cookies` key. Making the caller reshape their own
export first would be a papercut for no reason. --source-format and --mode are
sent only when passed.

`usage logs` exposes --endpoint, --only-current-token and --include-system
alongside the shared pagination flags. only_active is deliberately left out: it
is the generic listing filter and a request log is never active or inactive.

Two corrections come with them.

--instructions on `functions configure` is renamed --run-instructions, and its
help and both repositories' docs are rewritten. The field documents a function
for whoever calls it - how long a run takes, what each variable means, which
sites it trips over - and I had described it as configuration for the
self-healing agent, which is what the bare name reads like and is not what it
is. The API field is untouched; only the flag is renamed, through a new
command-scoped override in the generator so the name stays declared in one
place. Free to rename: v0.0.37 predates #84, so the flag has never shipped.

The skill checker now also requires documentation for a command that both runs
and has subcommands. `notte usage` is one as of this change, and the old
leaf-only rule would have let it slip out of the check the moment it grew
`usage logs`.

Verified against us-staging: `personas update` renames and reads back; the
other three are covered by mock-server tests asserting the request. `usage
logs` could not be verified live - /usage/logs returns 503 after ~25s to plain
curl on staging, before any of this code is involved.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
giordano-lucas added a commit that referenced this pull request Aug 31, 2026
The manifest #85 introduced listed five endpoints as "not exposed yet". Four of
them are worth having, so they are commands now and the skip lines are gone -
which is the file working as intended, as a list of decisions to revisit rather
than a place gaps go to be forgotten. `profiles duplicate` stays listed: it is
already proposed in #53.

  notte personas update --persona-id <id> --name ...
  notte profiles cookies --profile-id <id>
  notte profiles cookies-set --profile-id <id> --file cookies.json
  notte usage logs [--endpoint ...] [--page N] [--page-size N]

`personas update` is generated: PATCH /personas/{persona_id} is a JSON body
behind a $ref, so it needed an endpointMap entry and nothing else.

`profiles cookies-set` accepts either shape a cookies file comes in - a bare
array, which is what Playwright's storageState and the browser extensions
write, or an object with a `cookies` key. Making the caller reshape their own
export first would be a papercut for no reason. --source-format and --mode are
sent only when passed.

`usage logs` exposes --endpoint, --only-current-token and --include-system
alongside the shared pagination flags. only_active is deliberately left out: it
is the generic listing filter and a request log is never active or inactive.

Two corrections come with them.

--instructions on `functions configure` is renamed --run-instructions, and its
help and both repositories' docs are rewritten. The field documents a function
for whoever calls it - how long a run takes, what each variable means, which
sites it trips over - and I had described it as configuration for the
self-healing agent, which is what the bare name reads like and is not what it
is. The API field is untouched; only the flag is renamed, through a new
command-scoped override in the generator so the name stays declared in one
place. Free to rename: v0.0.37 predates #84, so the flag has never shipped.

The skill checker now also requires documentation for a command that both runs
and has subcommands. `notte usage` is one as of this change, and the old
leaf-only rule would have let it slip out of the check the moment it grew
`usage logs`.

Verified against us-staging: `personas update` renames and reads back; the
other three are covered by mock-server tests asserting the request. `usage
logs` could not be verified live - /usage/logs returns 503 after ~25s to plain
curl on staging, before any of this code is involved.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
giordano-lucas added a commit that referenced this pull request Aug 31, 2026
* feat: close four of the gaps the coverage manifest recorded

The manifest #85 introduced listed five endpoints as "not exposed yet". Four of
them are worth having, so they are commands now and the skip lines are gone -
which is the file working as intended, as a list of decisions to revisit rather
than a place gaps go to be forgotten. `profiles duplicate` stays listed: it is
already proposed in #53.

  notte personas update --persona-id <id> --name ...
  notte profiles cookies --profile-id <id>
  notte profiles cookies-set --profile-id <id> --file cookies.json
  notte usage logs [--endpoint ...] [--page N] [--page-size N]

`personas update` is generated: PATCH /personas/{persona_id} is a JSON body
behind a $ref, so it needed an endpointMap entry and nothing else.

`profiles cookies-set` accepts either shape a cookies file comes in - a bare
array, which is what Playwright's storageState and the browser extensions
write, or an object with a `cookies` key. Making the caller reshape their own
export first would be a papercut for no reason. --source-format and --mode are
sent only when passed.

`usage logs` exposes --endpoint, --only-current-token and --include-system
alongside the shared pagination flags. only_active is deliberately left out: it
is the generic listing filter and a request log is never active or inactive.

Two corrections come with them.

--instructions on `functions configure` is renamed --run-instructions, and its
help and both repositories' docs are rewritten. The field documents a function
for whoever calls it - how long a run takes, what each variable means, which
sites it trips over - and I had described it as configuration for the
self-healing agent, which is what the bare name reads like and is not what it
is. The API field is untouched; only the flag is renamed, through a new
command-scoped override in the generator so the name stays declared in one
place. Free to rename: v0.0.37 predates #84, so the flag has never shipped.

The skill checker now also requires documentation for a command that both runs
and has subcommands. `notte usage` is one as of this change, and the old
leaf-only rule would have let it slip out of the check the moment it grew
`usage logs`.

Verified against us-staging: `personas update` renames and reads back; the
other three are covered by mock-server tests asserting the request. `usage
logs` could not be verified live - /usage/logs returns 503 after ~25s to plain
curl on staging, before any of this code is involved.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: refuse an empty cookie set instead of emptying the profile

Greptile catch. `[]` parses fine as an array, so the bare-array branch sent an
empty cookie list - and --mode defaults to replace, so the API would have
emptied the profile. The wrapped-object branch already refused this; now both
do, through one error so they cannot drift apart again.

The test covers every shape that means "no cookies": a bare `[]`, a wrapped
empty list, an object with no cookies key, and whitespace. Each asserts nothing
reached the API, not just that an error came back.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant