open-research-protocol 0.4.20 → 0.4.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -326,6 +326,12 @@ For an agent or script, use stdin:
326
326
  printf '%s' 'sk-...' | orp secrets add --alias openai-primary --label "OpenAI Primary" --provider openai --value-stdin
327
327
  ```
328
328
 
329
+ If a service needs both a username and a secret, store the username with it:
330
+
331
+ ```bash
332
+ orp secrets add --alias huggingface-login --label "Hugging Face Login" --provider huggingface --kind password --username cody
333
+ ```
334
+
329
335
  After that:
330
336
 
331
337
  ```bash
@@ -356,6 +362,7 @@ does not contain the key itself. It means:
356
362
  For secrets, the simplest plain-English rule is:
357
363
 
358
364
  - `orp secrets add ...` = save a new key
365
+ - `orp secrets add ... --username <name>` = save a new login credential plus its username
359
366
  - `orp secrets list` = see what is saved
360
367
  - `orp secrets show ...` = inspect one saved key record
361
368
  - `orp secrets resolve ...` = get the key value for use right now
package/cli/orp.py CHANGED
@@ -10736,7 +10736,7 @@ def _about_payload() -> dict[str, Any]:
10736
10736
  "Frontier control is a built-in ORP ability exposed through `orp frontier ...`, separating the exact live point, the exact active milestone, the near structured checklist, and the farther major-version stack.",
10737
10737
  "Agent modes are lightweight optional overlays for taste, perspective shifts, and fresh movement; `orp mode nudge sleek-minimal-progressive --json` gives agents a deterministic reminder they can call on when they want a deeper, wider, top-down, or rotated lens without changing ORP's core artifact boundaries.",
10738
10738
  "Project/session linking is a built-in ORP ability exposed through `orp link ...` and stored machine-locally under `.git/orp/link/`.",
10739
- "Secrets are easiest to understand as saved keys and tokens: humans usually run `orp secrets add ...` and paste the value at the prompt, agents usually pipe the value with `--value-stdin`, and local macOS Keychain caching plus hosted sync are optional layers on top.",
10739
+ "Secrets are easiest to understand as saved credentials and related login metadata: humans usually run `orp secrets add ...` and paste the value at the prompt, agents usually pipe the value with `--value-stdin`, optional usernames can be stored alongside the secret when a service needs them, and local macOS Keychain caching plus hosted sync are optional layers on top.",
10740
10740
  "Connections give ORP one place to remember service accounts, public data sources, deployment targets, and which saved secret alias or named secret bindings power each integration through `orp connections providers`, `orp connections list`, `orp connections show`, `orp connections add`, `orp connections update`, `orp connections remove`, `orp connections sync`, and `orp connections pull`.",
10741
10741
  "Agenda refresh is built into ORP through `orp agenda refresh`, `orp agenda actions`, `orp agenda suggestions`, `orp agenda focus`, and `orp agenda set-north-star`, using a Codex reasoning pass over current workspace, GitHub, opportunities, and connection context to keep a ranked action list and a ranked suggestion list.",
10742
10742
  "Recurring agenda refreshes are always explicit opt-in. Nothing runs on a schedule until the user enables it with `orp agenda enable-refreshes`; `orp agenda refresh-status` shows the current state and default morning/afternoon/evening presets.",
@@ -10998,7 +10998,7 @@ def _home_payload(repo_root: Path, config_arg: str) -> dict[str, Any]:
10998
10998
  "command": "orp workspaces list --json",
10999
10999
  },
11000
11000
  {
11001
- "label": "Inspect saved keys and tokens already known to ORP",
11001
+ "label": "Inspect saved credentials and usernames already known to ORP",
11002
11002
  "command": "orp secrets list --json",
11003
11003
  },
11004
11004
  {
@@ -11365,7 +11365,7 @@ def _home_payload(repo_root: Path, config_arg: str) -> dict[str, Any]:
11365
11365
  },
11366
11366
  {
11367
11367
  "id": "secrets",
11368
- "description": "Saved API keys and tokens, with an interactive human flow, a stdin agent flow, optional local macOS Keychain caching, and optional hosted sync.",
11368
+ "description": "Saved API keys, tokens, passwords, and optional usernames, with an interactive human flow, a stdin agent flow, optional local macOS Keychain caching, and optional hosted sync.",
11369
11369
  "entrypoints": [
11370
11370
  "orp secrets list --json",
11371
11371
  "orp secrets show <alias-or-id> --json",
@@ -18573,6 +18573,7 @@ def _print_secret_human(
18573
18573
  ("secret.label", str(secret.get("label", "")).strip()),
18574
18574
  ("secret.provider", str(secret.get("provider", "")).strip()),
18575
18575
  ("secret.kind", str(secret.get("kind", "")).strip()),
18576
+ ("secret.username", str(secret.get("username", "")).strip()),
18576
18577
  ("secret.env_var_name", str(secret.get("envVarName", "")).strip()),
18577
18578
  ("secret.preview", str(secret.get("valuePreview", "")).strip()),
18578
18579
  ("secret.version", str(secret.get("valueVersion", "")).strip()),
@@ -18630,6 +18631,7 @@ def _keychain_comment_for_secret(secret: dict[str, Any]) -> str:
18630
18631
  "secret_id": str(secret.get("id", "")).strip(),
18631
18632
  "alias": str(secret.get("alias", "")).strip(),
18632
18633
  "provider": str(secret.get("provider", "")).strip(),
18634
+ "username": str(secret.get("username", "")).strip(),
18633
18635
  "env_var_name": str(secret.get("envVarName", "")).strip(),
18634
18636
  }
18635
18637
  return json.dumps(payload, sort_keys=True)
@@ -18692,6 +18694,7 @@ def _build_keychain_registry_entry(
18692
18694
  "label": str(secret.get("label", "")).strip(),
18693
18695
  "provider": str(secret.get("provider", "")).strip(),
18694
18696
  "kind": str(secret.get("kind", "")).strip(),
18697
+ "username": str(secret.get("username", "")).strip(),
18695
18698
  "env_var_name": str(secret.get("envVarName", "")).strip(),
18696
18699
  "status": str(secret.get("status", "")).strip(),
18697
18700
  "value_version": str(secret.get("valueVersion", "")).strip(),
@@ -18712,6 +18715,7 @@ def _secret_payload_from_keychain_entry(entry: dict[str, Any]) -> dict[str, Any]
18712
18715
  "label": str(entry.get("label", "")).strip(),
18713
18716
  "provider": str(entry.get("provider", "")).strip(),
18714
18717
  "kind": str(entry.get("kind", "")).strip(),
18718
+ "username": str(entry.get("username", "")).strip(),
18715
18719
  "envVarName": str(entry.get("env_var_name", "")).strip(),
18716
18720
  "status": str(entry.get("status", "")).strip(),
18717
18721
  "valueVersion": str(entry.get("value_version", "")).strip(),
@@ -20371,6 +20375,10 @@ def cmd_secrets_add(args: argparse.Namespace) -> int:
20371
20375
  "kind": str(getattr(args, "kind", "api_key")).strip() or "api_key",
20372
20376
  "value": value,
20373
20377
  }
20378
+ username = getattr(args, "username", None)
20379
+ if username is not None:
20380
+ text = str(username).strip()
20381
+ body["username"] = text or None
20374
20382
  env_var_name = getattr(args, "env_var_name", None)
20375
20383
  if env_var_name is not None:
20376
20384
  text = str(env_var_name).strip()
@@ -20427,6 +20435,10 @@ def cmd_secrets_ensure(args: argparse.Namespace) -> int:
20427
20435
  "kind": str(getattr(args, "kind", "api_key")).strip() or "api_key",
20428
20436
  "value": value,
20429
20437
  }
20438
+ username = getattr(args, "username", None)
20439
+ if username is not None:
20440
+ text = str(username).strip()
20441
+ body["username"] = text or None
20430
20442
  env_var_name = getattr(args, "env_var_name", None)
20431
20443
  if env_var_name is not None:
20432
20444
  text = str(env_var_name).strip()
@@ -20509,6 +20521,7 @@ def cmd_secrets_update(args: argparse.Namespace) -> int:
20509
20521
  ("label", "label"),
20510
20522
  ("provider", "provider"),
20511
20523
  ("kind", "kind"),
20524
+ ("username", "username"),
20512
20525
  ("env_var_name", "envVarName"),
20513
20526
  ("notes", "notes"),
20514
20527
  ("status", "status"),
@@ -20516,7 +20529,7 @@ def cmd_secrets_update(args: argparse.Namespace) -> int:
20516
20529
  value = getattr(args, attr_name, None)
20517
20530
  if value is not None:
20518
20531
  text = str(value).strip()
20519
- if body_key in {"envVarName", "notes"}:
20532
+ if body_key in {"username", "envVarName", "notes"}:
20520
20533
  body[body_key] = text or None
20521
20534
  else:
20522
20535
  body[body_key] = text
@@ -23197,9 +23210,9 @@ def build_parser() -> argparse.ArgumentParser:
23197
23210
 
23198
23211
  s_secrets = sub.add_parser(
23199
23212
  "secrets",
23200
- help="Save and reuse API keys and tokens locally, with optional hosted sync",
23213
+ help="Save and reuse API keys, tokens, passwords, and related login usernames",
23201
23214
  description=(
23202
- "ORP secrets are easiest to understand as saved keys and tokens.\n\n"
23215
+ "ORP secrets are easiest to understand as saved credentials and related login metadata.\n\n"
23203
23216
  "Human flow:\n"
23204
23217
  " 1. Run `orp secrets add ...`\n"
23205
23218
  " 2. Paste the value when ORP prompts `Secret value:`\n"
@@ -23211,6 +23224,7 @@ def build_parser() -> argparse.ArgumentParser:
23211
23224
  epilog=(
23212
23225
  "Examples:\n"
23213
23226
  " orp secrets add --alias openai-primary --label \"OpenAI Primary\" --provider openai\n"
23227
+ " orp secrets add --alias huggingface-login --label \"Hugging Face Login\" --provider huggingface --kind password --username cody\n"
23214
23228
  " printf '%s' 'sk-...' | orp secrets add --alias openai-primary --label \"OpenAI Primary\" --provider openai --value-stdin\n"
23215
23229
  " orp secrets list\n"
23216
23230
  " orp secrets resolve openai-primary --reveal"
@@ -23250,6 +23264,11 @@ def build_parser() -> argparse.ArgumentParser:
23250
23264
  default="api_key",
23251
23265
  help="Secret kind (default: api_key)",
23252
23266
  )
23267
+ s_secrets_add.add_argument(
23268
+ "--username",
23269
+ default=None,
23270
+ help="Optional username or login identifier that belongs with this credential",
23271
+ )
23253
23272
  s_secrets_add.add_argument("--env-var-name", default=None, help="Optional env var name, for example OPENAI_API_KEY")
23254
23273
  s_secrets_add.add_argument("--value", default=None, help="Secret value")
23255
23274
  s_secrets_add.add_argument(
@@ -23282,6 +23301,11 @@ def build_parser() -> argparse.ArgumentParser:
23282
23301
  default="api_key",
23283
23302
  help="Secret kind when create-if-missing is needed (default: api_key)",
23284
23303
  )
23304
+ s_secrets_ensure.add_argument(
23305
+ "--username",
23306
+ default=None,
23307
+ help="Optional username or login identifier to store on create-if-missing flows",
23308
+ )
23285
23309
  s_secrets_ensure.add_argument(
23286
23310
  "--env-var-name",
23287
23311
  default=None,
@@ -23359,6 +23383,7 @@ def build_parser() -> argparse.ArgumentParser:
23359
23383
  default=None,
23360
23384
  help="Secret kind",
23361
23385
  )
23386
+ s_secrets_update.add_argument("--username", default=None, help="Updated username or login identifier")
23362
23387
  s_secrets_update.add_argument("--env-var-name", default=None, help="Updated env var name")
23363
23388
  s_secrets_update.add_argument("--value", default=None, help="New secret value")
23364
23389
  s_secrets_update.add_argument(
@@ -61,6 +61,7 @@ read:
61
61
  - If the task needs an API key or token that is not already available, save it first:
62
62
  - human interactive path:
63
63
  - `orp secrets add --alias <alias> --label "<label>" --provider <provider>`
64
+ - `orp secrets add --alias <alias> --label "<label>" --provider <provider> --kind password --username <login>`
64
65
  - agent/script path:
65
66
  - `printf '%s' '<secret>' | orp secrets add --alias <alias> --label "<label>" --provider <provider> --value-stdin`
66
67
  - convenience path:
@@ -441,6 +441,17 @@ That is the clearest beginner flow:
441
441
  4. list or show it later
442
442
  5. resolve it when you need to use it
443
443
 
444
+ If the service needs a username too, save that alongside the secret:
445
+
446
+ ```bash
447
+ orp secrets add --alias huggingface-login --label "Hugging Face Login" --provider huggingface --kind password --username cody
448
+ ```
449
+
450
+ That means ORP can remember both:
451
+
452
+ - the secret value
453
+ - the related username/login identifier
454
+
444
455
  #### Agent or script flow
445
456
 
446
457
  If an agent or script needs to save a key non-interactively, use stdin:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-research-protocol",
3
- "version": "0.4.20",
3
+ "version": "0.4.21",
4
4
  "description": "ORP CLI (Open Research Protocol): workspace ledgers, secrets, scheduling, governed execution, and agent-friendly research workflows.",
5
5
  "license": "MIT",
6
6
  "author": "Fractal Research Group <cody@frg.earth>",