open-research-protocol 0.4.20 → 0.4.22
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 +7 -0
- package/cli/orp.py +41 -7
- package/docs/AGENT_LOOP.md +1 -0
- package/docs/START_HERE.md +11 -0
- package/package.json +1 -1
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
|
@@ -3443,6 +3443,9 @@ def _hosted_api_error(
|
|
|
3443
3443
|
payload: dict[str, Any] | None,
|
|
3444
3444
|
) -> HostedApiError:
|
|
3445
3445
|
message = str((payload or {}).get("error") or (payload or {}).get("message") or f"Request failed: {status}")
|
|
3446
|
+
stripped_message = message.lstrip()
|
|
3447
|
+
if stripped_message.startswith("<!DOCTYPE html") or stripped_message.startswith("<html"):
|
|
3448
|
+
message = "Hosted ORP returned an HTML error page instead of JSON"
|
|
3446
3449
|
suffix = f" (status={status} path={path})"
|
|
3447
3450
|
hint = ""
|
|
3448
3451
|
if status == 401:
|
|
@@ -3450,7 +3453,13 @@ def _hosted_api_error(
|
|
|
3450
3453
|
elif status == 403:
|
|
3451
3454
|
hint = " The hosted ORP app rejected the operation. Check permissions on the target record."
|
|
3452
3455
|
elif status == 404:
|
|
3453
|
-
|
|
3456
|
+
if message == "Hosted ORP returned an HTML error page instead of JSON":
|
|
3457
|
+
hint = (
|
|
3458
|
+
" The hosted API route may not be deployed at this base URL. "
|
|
3459
|
+
"Check ORP_BASE_URL or deploy the hosted ORP app."
|
|
3460
|
+
)
|
|
3461
|
+
else:
|
|
3462
|
+
hint = " The hosted record may have changed. Re-list the resource and retry."
|
|
3454
3463
|
elif status == 409:
|
|
3455
3464
|
hint = " The hosted record changed since you last fetched it. Re-open it and retry the update."
|
|
3456
3465
|
return HostedApiError(f"{message}{suffix}.{hint}".replace("..", "."))
|
|
@@ -10736,7 +10745,7 @@ def _about_payload() -> dict[str, Any]:
|
|
|
10736
10745
|
"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
10746
|
"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
10747
|
"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
|
|
10748
|
+
"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
10749
|
"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
10750
|
"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
10751
|
"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 +11007,7 @@ def _home_payload(repo_root: Path, config_arg: str) -> dict[str, Any]:
|
|
|
10998
11007
|
"command": "orp workspaces list --json",
|
|
10999
11008
|
},
|
|
11000
11009
|
{
|
|
11001
|
-
"label": "Inspect saved
|
|
11010
|
+
"label": "Inspect saved credentials and usernames already known to ORP",
|
|
11002
11011
|
"command": "orp secrets list --json",
|
|
11003
11012
|
},
|
|
11004
11013
|
{
|
|
@@ -11365,7 +11374,7 @@ def _home_payload(repo_root: Path, config_arg: str) -> dict[str, Any]:
|
|
|
11365
11374
|
},
|
|
11366
11375
|
{
|
|
11367
11376
|
"id": "secrets",
|
|
11368
|
-
"description": "Saved API keys and
|
|
11377
|
+
"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
11378
|
"entrypoints": [
|
|
11370
11379
|
"orp secrets list --json",
|
|
11371
11380
|
"orp secrets show <alias-or-id> --json",
|
|
@@ -18573,6 +18582,7 @@ def _print_secret_human(
|
|
|
18573
18582
|
("secret.label", str(secret.get("label", "")).strip()),
|
|
18574
18583
|
("secret.provider", str(secret.get("provider", "")).strip()),
|
|
18575
18584
|
("secret.kind", str(secret.get("kind", "")).strip()),
|
|
18585
|
+
("secret.username", str(secret.get("username", "")).strip()),
|
|
18576
18586
|
("secret.env_var_name", str(secret.get("envVarName", "")).strip()),
|
|
18577
18587
|
("secret.preview", str(secret.get("valuePreview", "")).strip()),
|
|
18578
18588
|
("secret.version", str(secret.get("valueVersion", "")).strip()),
|
|
@@ -18630,6 +18640,7 @@ def _keychain_comment_for_secret(secret: dict[str, Any]) -> str:
|
|
|
18630
18640
|
"secret_id": str(secret.get("id", "")).strip(),
|
|
18631
18641
|
"alias": str(secret.get("alias", "")).strip(),
|
|
18632
18642
|
"provider": str(secret.get("provider", "")).strip(),
|
|
18643
|
+
"username": str(secret.get("username", "")).strip(),
|
|
18633
18644
|
"env_var_name": str(secret.get("envVarName", "")).strip(),
|
|
18634
18645
|
}
|
|
18635
18646
|
return json.dumps(payload, sort_keys=True)
|
|
@@ -18692,6 +18703,7 @@ def _build_keychain_registry_entry(
|
|
|
18692
18703
|
"label": str(secret.get("label", "")).strip(),
|
|
18693
18704
|
"provider": str(secret.get("provider", "")).strip(),
|
|
18694
18705
|
"kind": str(secret.get("kind", "")).strip(),
|
|
18706
|
+
"username": str(secret.get("username", "")).strip(),
|
|
18695
18707
|
"env_var_name": str(secret.get("envVarName", "")).strip(),
|
|
18696
18708
|
"status": str(secret.get("status", "")).strip(),
|
|
18697
18709
|
"value_version": str(secret.get("valueVersion", "")).strip(),
|
|
@@ -18712,6 +18724,7 @@ def _secret_payload_from_keychain_entry(entry: dict[str, Any]) -> dict[str, Any]
|
|
|
18712
18724
|
"label": str(entry.get("label", "")).strip(),
|
|
18713
18725
|
"provider": str(entry.get("provider", "")).strip(),
|
|
18714
18726
|
"kind": str(entry.get("kind", "")).strip(),
|
|
18727
|
+
"username": str(entry.get("username", "")).strip(),
|
|
18715
18728
|
"envVarName": str(entry.get("env_var_name", "")).strip(),
|
|
18716
18729
|
"status": str(entry.get("status", "")).strip(),
|
|
18717
18730
|
"valueVersion": str(entry.get("value_version", "")).strip(),
|
|
@@ -20371,6 +20384,10 @@ def cmd_secrets_add(args: argparse.Namespace) -> int:
|
|
|
20371
20384
|
"kind": str(getattr(args, "kind", "api_key")).strip() or "api_key",
|
|
20372
20385
|
"value": value,
|
|
20373
20386
|
}
|
|
20387
|
+
username = getattr(args, "username", None)
|
|
20388
|
+
if username is not None:
|
|
20389
|
+
text = str(username).strip()
|
|
20390
|
+
body["username"] = text or None
|
|
20374
20391
|
env_var_name = getattr(args, "env_var_name", None)
|
|
20375
20392
|
if env_var_name is not None:
|
|
20376
20393
|
text = str(env_var_name).strip()
|
|
@@ -20427,6 +20444,10 @@ def cmd_secrets_ensure(args: argparse.Namespace) -> int:
|
|
|
20427
20444
|
"kind": str(getattr(args, "kind", "api_key")).strip() or "api_key",
|
|
20428
20445
|
"value": value,
|
|
20429
20446
|
}
|
|
20447
|
+
username = getattr(args, "username", None)
|
|
20448
|
+
if username is not None:
|
|
20449
|
+
text = str(username).strip()
|
|
20450
|
+
body["username"] = text or None
|
|
20430
20451
|
env_var_name = getattr(args, "env_var_name", None)
|
|
20431
20452
|
if env_var_name is not None:
|
|
20432
20453
|
text = str(env_var_name).strip()
|
|
@@ -20509,6 +20530,7 @@ def cmd_secrets_update(args: argparse.Namespace) -> int:
|
|
|
20509
20530
|
("label", "label"),
|
|
20510
20531
|
("provider", "provider"),
|
|
20511
20532
|
("kind", "kind"),
|
|
20533
|
+
("username", "username"),
|
|
20512
20534
|
("env_var_name", "envVarName"),
|
|
20513
20535
|
("notes", "notes"),
|
|
20514
20536
|
("status", "status"),
|
|
@@ -20516,7 +20538,7 @@ def cmd_secrets_update(args: argparse.Namespace) -> int:
|
|
|
20516
20538
|
value = getattr(args, attr_name, None)
|
|
20517
20539
|
if value is not None:
|
|
20518
20540
|
text = str(value).strip()
|
|
20519
|
-
if body_key in {"envVarName", "notes"}:
|
|
20541
|
+
if body_key in {"username", "envVarName", "notes"}:
|
|
20520
20542
|
body[body_key] = text or None
|
|
20521
20543
|
else:
|
|
20522
20544
|
body[body_key] = text
|
|
@@ -23197,9 +23219,9 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
23197
23219
|
|
|
23198
23220
|
s_secrets = sub.add_parser(
|
|
23199
23221
|
"secrets",
|
|
23200
|
-
help="Save and reuse API keys
|
|
23222
|
+
help="Save and reuse API keys, tokens, passwords, and related login usernames",
|
|
23201
23223
|
description=(
|
|
23202
|
-
"ORP secrets are easiest to understand as saved
|
|
23224
|
+
"ORP secrets are easiest to understand as saved credentials and related login metadata.\n\n"
|
|
23203
23225
|
"Human flow:\n"
|
|
23204
23226
|
" 1. Run `orp secrets add ...`\n"
|
|
23205
23227
|
" 2. Paste the value when ORP prompts `Secret value:`\n"
|
|
@@ -23211,6 +23233,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
23211
23233
|
epilog=(
|
|
23212
23234
|
"Examples:\n"
|
|
23213
23235
|
" orp secrets add --alias openai-primary --label \"OpenAI Primary\" --provider openai\n"
|
|
23236
|
+
" orp secrets add --alias huggingface-login --label \"Hugging Face Login\" --provider huggingface --kind password --username cody\n"
|
|
23214
23237
|
" printf '%s' 'sk-...' | orp secrets add --alias openai-primary --label \"OpenAI Primary\" --provider openai --value-stdin\n"
|
|
23215
23238
|
" orp secrets list\n"
|
|
23216
23239
|
" orp secrets resolve openai-primary --reveal"
|
|
@@ -23250,6 +23273,11 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
23250
23273
|
default="api_key",
|
|
23251
23274
|
help="Secret kind (default: api_key)",
|
|
23252
23275
|
)
|
|
23276
|
+
s_secrets_add.add_argument(
|
|
23277
|
+
"--username",
|
|
23278
|
+
default=None,
|
|
23279
|
+
help="Optional username or login identifier that belongs with this credential",
|
|
23280
|
+
)
|
|
23253
23281
|
s_secrets_add.add_argument("--env-var-name", default=None, help="Optional env var name, for example OPENAI_API_KEY")
|
|
23254
23282
|
s_secrets_add.add_argument("--value", default=None, help="Secret value")
|
|
23255
23283
|
s_secrets_add.add_argument(
|
|
@@ -23282,6 +23310,11 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
23282
23310
|
default="api_key",
|
|
23283
23311
|
help="Secret kind when create-if-missing is needed (default: api_key)",
|
|
23284
23312
|
)
|
|
23313
|
+
s_secrets_ensure.add_argument(
|
|
23314
|
+
"--username",
|
|
23315
|
+
default=None,
|
|
23316
|
+
help="Optional username or login identifier to store on create-if-missing flows",
|
|
23317
|
+
)
|
|
23285
23318
|
s_secrets_ensure.add_argument(
|
|
23286
23319
|
"--env-var-name",
|
|
23287
23320
|
default=None,
|
|
@@ -23359,6 +23392,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
23359
23392
|
default=None,
|
|
23360
23393
|
help="Secret kind",
|
|
23361
23394
|
)
|
|
23395
|
+
s_secrets_update.add_argument("--username", default=None, help="Updated username or login identifier")
|
|
23362
23396
|
s_secrets_update.add_argument("--env-var-name", default=None, help="Updated env var name")
|
|
23363
23397
|
s_secrets_update.add_argument("--value", default=None, help="New secret value")
|
|
23364
23398
|
s_secrets_update.add_argument(
|
package/docs/AGENT_LOOP.md
CHANGED
|
@@ -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:
|
package/docs/START_HERE.md
CHANGED
|
@@ -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.
|
|
3
|
+
"version": "0.4.22",
|
|
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>",
|