delegate-agent-cli 0.24.0__tar.gz → 0.25.0__tar.gz
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.
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/CHANGELOG.md +50 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/PKG-INFO +1 -1
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/bin/delegate-profile-shim +1 -1
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/config.example.json +3 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/docs/cli-reference.md +41 -1
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/docs/configuration.md +24 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/docs/delegate-workflows.md +16 -4
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/docs/security-model.md +25 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/pyproject.toml +1 -1
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/__init__.py +1 -1
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/argv_builders.py +5 -7
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/cli.py +56 -1
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/cli_parser.py +103 -1
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/command_help.py +63 -1
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/config.py +17 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/constants.py +13 -1
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/describe_payload.py +27 -2
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/harness_discovery.py +60 -1
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/isolation.py +6 -0
- delegate_agent_cli-0.25.0/src/delegate_agent/personas.py +199 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/profile_guard.py +1 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/prompt_instructions.py +7 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/prompt_transport.py +6 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/request_build.py +443 -63
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/request_models.py +33 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/resume_command.py +61 -2
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/run_metadata.py +8 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/run_registry.py +1 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/run_status.py +5 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/runner.py +47 -1
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/snapshot_view.py +5 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/workflows/runtime.py +110 -11
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/worktree_execution.py +64 -20
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent_cli.egg-info/PKG-INFO +1 -1
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent_cli.egg-info/SOURCES.txt +12 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_command_help.py +1 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_engine_argv.py +18 -8
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_execution_argv_and_prompt.py +11 -1
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_harness_discovery.py +17 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_kimi_commands.py +5 -2
- delegate_agent_cli-0.25.0/tests/test_persona_capability.py +214 -0
- delegate_agent_cli-0.25.0/tests/test_persona_claude.py +87 -0
- delegate_agent_cli-0.25.0/tests/test_persona_contract.py +79 -0
- delegate_agent_cli-0.25.0/tests/test_persona_framer.py +454 -0
- delegate_agent_cli-0.25.0/tests/test_persona_opencode.py +146 -0
- delegate_agent_cli-0.25.0/tests/test_persona_parser.py +176 -0
- delegate_agent_cli-0.25.0/tests/test_persona_records.py +574 -0
- delegate_agent_cli-0.25.0/tests/test_persona_resolution.py +300 -0
- delegate_agent_cli-0.25.0/tests/test_persona_size_guard.py +185 -0
- delegate_agent_cli-0.25.0/tests/test_persona_validation.py +107 -0
- delegate_agent_cli-0.25.0/tests/test_persona_workflow.py +445 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_resume_attachment.py +4 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_resume_size_guard.py +24 -25
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_workflow_commands.py +7 -3
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/CONTRIBUTING.md +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/LICENSE +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/MANIFEST.in +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/README.md +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/SECURITY.md +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/bin/delegate.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/docs/agent-setup.md +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/docs/assets/delegate-agent-header.png +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/docs/development.md +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/docs/live-runtime.md +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/docs/publishing-checklist.md +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/docs/troubleshooting.md +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/docs/worktrees.md +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/examples/task.claude.json +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/examples/task.codex.json +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/examples/task.cursor.json +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/examples/task.droid.json +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/examples/task.grok.json +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/examples/task.judge.json +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/examples/task.kimi.json +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/setup.cfg +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/archived_logs.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/argv_utils.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/bundled_models.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/capability_commands.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/child_failures.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/command_errors.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/config_commands.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/errors.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/git_utils.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/harness_events.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/inspection_commands.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/json_types.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/log_output.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/model_discovery.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/private_io.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/profile_commands.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/profiles.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/reasoning.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/redaction.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/rendering.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/retention.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/run_output_commands.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/safe_workspace.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/seatbelt.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/setup_commands.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/structured_output.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/wait_cancel_commands.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/workflows/__init__.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/workflows/commands.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/workflows/registry.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/workflows/schema.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/workflows/script.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/worktree_commands.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/worktree_gc.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/worktree_mgmt.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/worktree_records.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/worktree_remove.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/worktree_summary.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent/wsl.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent_cli.egg-info/dependency_links.txt +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent_cli.egg-info/entry_points.txt +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent_cli.egg-info/requires.txt +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/src/delegate_agent_cli.egg-info/top_level.txt +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_capability_commands.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_child_failures.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_codex_pure_sandbox.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_codex_thread_resilience.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_config_commands.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_delegate_help_cli.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_delegate_isolation.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_delegate_parser.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_delegate_validation.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_end_to_end_tracking.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_execution_dry_run.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_execution_worktree_failure_cleanup.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_execution_worktree_preflight.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_execution_worktree_run.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_harness_events.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_inspection_commands.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_model_discovery.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_model_selection_wave1a.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_model_selection_wave1b.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_omp_read_only_behavior.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_packaging.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_profiles.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_pure_call.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_reasoning_capabilities.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_resume_capture.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_resume_inheritance.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_resume_parser.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_resume_projections.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_resume_refusals.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_resume_stale.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_resume_trust.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_retention.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_run_registry.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_runner_capture.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_safe_workspace_isolation.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_setup_commands.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_slash_passthrough.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_snapshot_redaction.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_snapshot_rendering.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_snapshot_run_output.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_snapshot_view.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_structured_output.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_tracked_timeout.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_utility_modules.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_wait_cancel_commands.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_wave4_launch_features.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_worktree_list_show.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_worktree_prune_gc.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_worktree_remove.py +0 -0
- {delegate_agent_cli-0.24.0 → delegate_agent_cli-0.25.0}/tests/test_wsl_guardrails.py +0 -0
|
@@ -5,6 +5,55 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.25.0] - 2026-08-01
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Named personas: `--persona` / `--no-persona` / `--allow-repo-persona` on
|
|
15
|
+
every engine's safe/work launch (and dry-run), input-json `persona` /
|
|
16
|
+
`allowRepoPersona` keys, and workflow `agent(persona=...)` with the resolved
|
|
17
|
+
persona digest pinned into the structural cache key so an edited persona is
|
|
18
|
+
a cache miss by design.
|
|
19
|
+
- `delegate personas [--json]` listing (schema `delegate.personas.v1`) with
|
|
20
|
+
workspace-shadowing metadata and per-file invalid rows; read-only allowlisted
|
|
21
|
+
in both the profile guard and the shell shim.
|
|
22
|
+
- Persona transports: claude work uses `--append-system-prompt-file` with a
|
|
23
|
+
private 0600 file when discovery positively proves current support (probe
|
|
24
|
+
recognizes both the long and the collapsed `--append-system-prompt[-file]`
|
|
25
|
+
help spellings); opencode merges a synthetic `delegate-persona` agent into
|
|
26
|
+
the effective config without clobbering profile keys; every other engine
|
|
27
|
+
prepends. Safe mode always prepends, with the persona placed before the
|
|
28
|
+
safe policy so the safety text keeps recency.
|
|
29
|
+
- `persona.txt` as a private durable run artifact with manifest, snapshot,
|
|
30
|
+
and runs-summary projection; resume replays recorded persona bytes through
|
|
31
|
+
the target engine's transport, `--persona` re-resolves, `--no-persona`
|
|
32
|
+
drops.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- The central framer is now the sole prompt composer: cursor/droid/kimi argv
|
|
37
|
+
builders no longer self-prefix safe policy text, user and persona bytes are
|
|
38
|
+
joined verbatim, and persistent/attached worktree notes are tracked
|
|
39
|
+
structurally on the request rather than inferred from prompt content.
|
|
40
|
+
- Slash-passthrough prompts on persistent or attached worktree runs carry the
|
|
41
|
+
Delegate-owned worktree and forbid-commit notes ahead of the slash command,
|
|
42
|
+
matching v0.24.0 behavior; all other slash payloads remain byte-verbatim.
|
|
43
|
+
|
|
44
|
+
### Security
|
|
45
|
+
|
|
46
|
+
- Persona resolution walks `.delegate/personas` component-by-component over
|
|
47
|
+
`O_NOFOLLOW` descriptors anchored at the source workspace or home, refusing
|
|
48
|
+
symlinked parents and leaves; strict UTF-8, C0 refusal, and a 64 KiB cap.
|
|
49
|
+
- Resume persona replay reads only the fixed `persona.txt` artifact with a
|
|
50
|
+
required, verified sha256 digest; manifest data cannot redirect the read.
|
|
51
|
+
- The claude native persona gate fails closed: probe errors, timeouts, and
|
|
52
|
+
unrecognized banners fall back to prepend so an older binary never receives
|
|
53
|
+
an unknown flag. Dry-run never probes.
|
|
54
|
+
- Workflow persona digests travel across the child seam and both sides fail
|
|
55
|
+
closed on mismatch without caching.
|
|
56
|
+
|
|
8
57
|
## [0.24.0] - 2026-07-31
|
|
9
58
|
|
|
10
59
|
### Added
|
|
@@ -783,6 +832,7 @@ Usage-audit fix wave: 82 sessions and 1,241 delegate invocations from one week o
|
|
|
783
832
|
|
|
784
833
|
- Releases before 0.1.3 predate this changelog.
|
|
785
834
|
|
|
835
|
+
[0.25.0]: https://github.com/treygoff24/delegate-agent/compare/v0.24.0...v0.25.0
|
|
786
836
|
[0.24.0]: https://github.com/treygoff24/delegate-agent/compare/v0.23.0...v0.24.0
|
|
787
837
|
[0.23.0]: https://github.com/treygoff24/delegate-agent/compare/v0.22.0...v0.23.0
|
|
788
838
|
[0.22.0]: https://github.com/treygoff24/delegate-agent/compare/v0.21.0...v0.22.0
|
|
@@ -134,7 +134,7 @@ _delegate_is_readonly_request() {
|
|
|
134
134
|
esac
|
|
135
135
|
done
|
|
136
136
|
case "$_cmd" in
|
|
137
|
-
profiles|runs|ps|run-output|describe|snapshot|agent-help|help|--help|-h|--version)
|
|
137
|
+
profiles|runs|ps|run-output|describe|snapshot|agent-help|personas|help|--help|-h|--version)
|
|
138
138
|
return 0
|
|
139
139
|
;;
|
|
140
140
|
models)
|
|
@@ -15,6 +15,46 @@ Use `delegate --help` for the exact command list from the installed version. Glo
|
|
|
15
15
|
--group NAME Tag a launch/run-input request with a lightweight group ([A-Za-z0-9._-]{1,64}).
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
+
## Personas
|
|
19
|
+
|
|
20
|
+
Named personas are UTF-8 Markdown files resolved from the source workspace:
|
|
21
|
+
`.delegate/personas/<name>.md` shadows `~/.delegate/personas/<name>.md`. Names
|
|
22
|
+
must match `[A-Za-z0-9][A-Za-z0-9._-]{0,63}`; files are regular, non-symlink
|
|
23
|
+
files no larger than 64 KiB and are rejected on invalid UTF-8 or disallowed C0
|
|
24
|
+
controls. The workspace-local directory is not VCS-shared by default; teams
|
|
25
|
+
that intentionally version a persona must force-add that individual file.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
delegate personas
|
|
29
|
+
delegate --json personas
|
|
30
|
+
delegate claude work --persona editor "Review chapter 3"
|
|
31
|
+
delegate codex safe --persona editor --allow-repo-persona "Review the diff"
|
|
32
|
+
delegate resume --persona editor <handle> "Continue with the requested fixes"
|
|
33
|
+
delegate resume --no-persona <handle> "Continue without the recorded persona"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`--persona NAME`, `--no-persona`, and `--allow-repo-persona` are shared launch
|
|
37
|
+
options. A workspace-local persona is refused in safe mode unless explicitly
|
|
38
|
+
allowed. Resolution logs `persona: NAME (workspace|global)` to stderr. Personas
|
|
39
|
+
are not accepted for call, read-only call, `--pass-through`, or slash-passthrough
|
|
40
|
+
prompts. Input JSON uses `persona` (string or null) and `allowRepoPersona`
|
|
41
|
+
(boolean).
|
|
42
|
+
|
|
43
|
+
`delegate --json personas` returns schema `delegate.personas.v1` with sorted rows
|
|
44
|
+
containing `name`, `source`, `sizeBytes`, and an escaped bounded `preview`.
|
|
45
|
+
Invalid files remain visible with an `invalid` reason; a workspace row that
|
|
46
|
+
shadows a global row also includes `shadowsGlobal: true`.
|
|
47
|
+
|
|
48
|
+
Work-mode transport is prepend for most engines, Claude native-file only when
|
|
49
|
+
the discovery cache proves `--append-system-prompt-file` (otherwise prepend
|
|
50
|
+
with a warning), and OpenCode agent-config merge. OpenCode preserves existing
|
|
51
|
+
root keys, agent keys, and prompts, appending the persona after an existing
|
|
52
|
+
agent prompt. Safe mode always prepends. Claude native-file keeps the persona
|
|
53
|
+
body out of argv, dry-run JSON, and the manifest; prepend engines using argv
|
|
54
|
+
transport (Cursor, Kimi, and Oh My Pi) expose it in the live process argv.
|
|
55
|
+
Tracked runs retain it only in the private
|
|
56
|
+
`persona.txt` artifact.
|
|
57
|
+
|
|
18
58
|
## Commands
|
|
19
59
|
|
|
20
60
|
### Direct runtime commands
|
|
@@ -420,7 +460,7 @@ delegate [--json] workflow save <script.py> --name NAME
|
|
|
420
460
|
- `run` launches a detached supervisor; `--dry-run` renders planned stubs
|
|
421
461
|
without launching child agents or consuming real budget. Each entry in
|
|
422
462
|
`runTree.calls` includes the resolved `model`, `effort`, `fast`, `isolation`,
|
|
423
|
-
and UTF-8 `promptBytes`; Cursor/Kimi prompts over 102400 bytes add a warning
|
|
463
|
+
and UTF-8 `promptBytes`; Cursor/Kimi/OMP prompts over 102400 bytes add a warning
|
|
424
464
|
before their argv transport limit can fail a real run.
|
|
425
465
|
- `--resume` replays the journal, adopts matching child runs by workflow agent
|
|
426
466
|
key, and continues from missing work.
|
|
@@ -201,6 +201,30 @@ reasoning defaults.
|
|
|
201
201
|
|
|
202
202
|
## Sections
|
|
203
203
|
|
|
204
|
+
### `personas`
|
|
205
|
+
|
|
206
|
+
Persona files are workspace-local by design, not VCS-shared configuration:
|
|
207
|
+
`.delegate/personas/*.md` shadows the same name under
|
|
208
|
+
`~/.delegate/personas/`. The `delegate personas` command lists both scopes
|
|
209
|
+
without exposing persona bodies in JSON previews. Because `.delegate` is
|
|
210
|
+
normally excluded, teams that intentionally version a persona must force-add
|
|
211
|
+
the individual file; the resolution scope remains workspace-local.
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"personas": {
|
|
216
|
+
"forceTransport": null
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
`forceTransport` is optional and accepts `null`, `prepend`, `native-file`, or
|
|
222
|
+
`agent-config`. It is an explicit transport pin, not a capability probe;
|
|
223
|
+
`native-file` is appropriate only when the configured Claude binary supports
|
|
224
|
+
`--append-system-prompt-file`, and `agent-config` is meaningful for OpenCode.
|
|
225
|
+
Safe mode never uses native persona channels. A workspace-local persona is
|
|
226
|
+
refused in safe mode unless the launch includes `--allow-repo-persona`.
|
|
227
|
+
|
|
204
228
|
### `tracking`
|
|
205
229
|
|
|
206
230
|
Controls local run recording.
|
|
@@ -64,7 +64,7 @@ workflow result in `result.json`. Injected globals are `agent`, `pipeline`,
|
|
|
64
64
|
|
|
65
65
|
## Core DSL
|
|
66
66
|
|
|
67
|
-
- `agent(prompt, engine=None, mode=None, model=None, effort=None, schema=None, label=None, phase=None, isolation=None, passthrough=False, timeout=None, retries=None, fast=None)` launches a real Delegate child run and returns parent-facing output, a validated schema object, or `None`. `fast=True` requests Codex Fast, `fast=False` requests Standard, and `None` inherits; non-Codex fallback candidates ignore this Codex-only preference. `
|
|
67
|
+
- `agent(prompt, engine=None, mode=None, model=None, effort=None, schema=None, label=None, phase=None, isolation=None, passthrough=False, timeout=None, retries=None, fast=None, persona=None, allow_repo_persona=False)` launches a real Delegate child run and returns parent-facing output, a validated schema object, or `None`. `fast=True` requests Codex Fast, `fast=False` requests Standard, and `None` inherits; non-Codex fallback candidates ignore this Codex-only preference. `persona` resolves one named persona from the source workspace; `allow_repo_persona=True` opts into workspace-local personas in safe mode.
|
|
68
68
|
- `pipeline(items, stage1, ...)` runs per-item stage chains with no inter-stage barrier. A throwing stage drops that item to `None` and skips later stages for that item.
|
|
69
69
|
- `parallel([lambda: ...])` is a barrier and preserves order. Ordinary item failures become `None` slots; gate checkpoints propagate to the supervisor.
|
|
70
70
|
- `phase(title)` emits a progress event.
|
|
@@ -76,6 +76,17 @@ Workflow `engine` values and `workflows.engineCaps` keys accept `cursor`,
|
|
|
76
76
|
`droid`, `codex`, `claude`, `grok`, `devin`, `opencode`, `pi`, `omp`, and
|
|
77
77
|
`kimi`.
|
|
78
78
|
|
|
79
|
+
### Persona digest pinning
|
|
80
|
+
|
|
81
|
+
When `agent(persona="editor")` first resolves `editor.md`, the workflow
|
|
82
|
+
structural key and `agent_started` journal event include the resolved bytes'
|
|
83
|
+
SHA-256 digest. Replay therefore returns the result only for the same persona
|
|
84
|
+
version: editing the file creates a cache miss instead of mixing two versions
|
|
85
|
+
under the same name. Dry-runs expose persona name/source/digest/byte count but
|
|
86
|
+
never write the persona body. Child input JSON carries `persona` and
|
|
87
|
+
`allowRepoPersona`; the normal run manifest and inspection projections expose
|
|
88
|
+
non-sensitive persona metadata only.
|
|
89
|
+
|
|
79
90
|
## Gates and resume
|
|
80
91
|
|
|
81
92
|
A workflow gate checkpoints the whole workflow tree, not just the nested child
|
|
@@ -200,9 +211,10 @@ python3 bin/delegate.py --json workflow run review.py \
|
|
|
200
211
|
```
|
|
201
212
|
|
|
202
213
|
The preview's `runTree.calls` records each call's resolved `model`, `effort`,
|
|
203
|
-
`fast`, `isolation`, and UTF-8 `promptBytes
|
|
204
|
-
|
|
205
|
-
prompt
|
|
214
|
+
`fast`, `isolation`, and UTF-8 `promptBytes` (the raw user prompt plus resolved
|
|
215
|
+
persona text). Cursor, Kimi, and OMP calls whose user-plus-resolved-persona input
|
|
216
|
+
exceeds 102400 bytes carry a warning; the final materialized prompt is checked
|
|
217
|
+
again before exec.
|
|
206
218
|
|
|
207
219
|
## CLI
|
|
208
220
|
|
|
@@ -13,6 +13,31 @@ Delegate controls:
|
|
|
13
13
|
- Prompt framing that tells sub-agents to review available skills and, in safe mode, avoid edits.
|
|
14
14
|
- Local run metadata under `.delegate/` for tracked runs.
|
|
15
15
|
|
|
16
|
+
### Persona boundary
|
|
17
|
+
|
|
18
|
+
Personas are untrusted prompt text, not policy. Delegate validates the name,
|
|
19
|
+
path containment, file type, UTF-8, byte limit, and C0 controls, but does not
|
|
20
|
+
trust persona instructions. Safe-mode framing deliberately places the safe
|
|
21
|
+
advisory after the persona (`skill -> persona -> safe`) so a persona cannot
|
|
22
|
+
replace the safety text by recency. Native persona channels are work-only;
|
|
23
|
+
safe mode always prepends.
|
|
24
|
+
|
|
25
|
+
Workspace-local personas live under `.delegate/personas/`, which is local state
|
|
26
|
+
and is not VCS-shared. Safe mode refuses them by default; use
|
|
27
|
+
`--allow-repo-persona` only when the source workspace is trusted. Global
|
|
28
|
+
personas are resolved from `~/.delegate/personas/` when no workspace file
|
|
29
|
+
shadows the name. Call, read-only call, pass-through, and slash-passthrough
|
|
30
|
+
surfaces refuse personas rather than silently changing their prompt contract.
|
|
31
|
+
|
|
32
|
+
Claude native-file transport is discovery-gated and writes a private 0600 file;
|
|
33
|
+
an absent, stale, or unproven capability falls back to prepend. OpenCode merges
|
|
34
|
+
into the effective config without destroying existing root keys, agent fields,
|
|
35
|
+
or prompt text; malformed config falls back to prepend with a warning. Claude
|
|
36
|
+
native-file keeps persona bodies out of argv, dry-run output, and manifests;
|
|
37
|
+
prepend engines using argv transport expose them in the live process argv.
|
|
38
|
+
Tracked runs retain
|
|
39
|
+
the resolved bytes only in private `persona.txt`, which is removed with the run.
|
|
40
|
+
|
|
16
41
|
Delegate does not control:
|
|
17
42
|
|
|
18
43
|
- The child runtime's implementation.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "delegate-agent-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.25.0"
|
|
8
8
|
description = "A tiny CLI for delegating bounded agent tasks across coding-agent runtimes."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -20,6 +20,7 @@ from delegate_agent.prompt_transport import (
|
|
|
20
20
|
CURSOR_PROMPT_REDACTION,
|
|
21
21
|
DEVIN_AGENT_CONFIG_ARG_PLACEHOLDER,
|
|
22
22
|
DROID_PROMPT_FILE_ARG_PLACEHOLDER,
|
|
23
|
+
PERSONA_FILE_ARG_PLACEHOLDER,
|
|
23
24
|
PROMPT_FILE_ARG_PLACEHOLDER,
|
|
24
25
|
PROMPT_TRANSPORT_ARGV,
|
|
25
26
|
PROMPT_TRANSPORT_FILE,
|
|
@@ -176,8 +177,6 @@ def build_cursor_argv(
|
|
|
176
177
|
argv = [*prefix, "--workspace", workspace, "-p", "--trust"]
|
|
177
178
|
if mode == MODE_WORK:
|
|
178
179
|
argv.extend(["--approve-mcps", "--force"])
|
|
179
|
-
elif mode == MODE_SAFE:
|
|
180
|
-
prompt = prefix_cursor_safe_prompt(prompt)
|
|
181
180
|
elif mode == MODE_CALL:
|
|
182
181
|
# Call defaults to work-level capability ("work minus a repo"); --read-only
|
|
183
182
|
# drops the write flags for the stateless judge/completion contract.
|
|
@@ -209,8 +208,6 @@ def build_droid_argv(
|
|
|
209
208
|
argv = [binary, "exec", "--cwd", workspace]
|
|
210
209
|
if mode == MODE_WORK:
|
|
211
210
|
argv.append("--skip-permissions-unsafe")
|
|
212
|
-
elif mode == MODE_SAFE:
|
|
213
|
-
prompt = prefix_droid_safe_prompt(prompt)
|
|
214
211
|
elif mode == MODE_CALL:
|
|
215
212
|
if not call_read_only:
|
|
216
213
|
argv.append("--skip-permissions-unsafe")
|
|
@@ -246,9 +243,7 @@ def build_kimi_argv(
|
|
|
246
243
|
) -> list[str]:
|
|
247
244
|
_reject_pure("kimi", mode, pure)
|
|
248
245
|
argv = [str(kimi["binary"])]
|
|
249
|
-
if mode
|
|
250
|
-
prompt = prefix_kimi_safe_prompt(prompt)
|
|
251
|
-
elif mode not in (MODE_WORK, MODE_CALL):
|
|
246
|
+
if mode not in (MODE_SAFE, MODE_WORK, MODE_CALL):
|
|
252
247
|
validate_mode(mode)
|
|
253
248
|
if model:
|
|
254
249
|
argv.extend(["--model", model])
|
|
@@ -270,6 +265,7 @@ def build_claude_argv(
|
|
|
270
265
|
call_read_only: bool = False,
|
|
271
266
|
pure: bool = False,
|
|
272
267
|
output_schema: str | None = None,
|
|
268
|
+
persona_file: bool = False,
|
|
273
269
|
) -> list[str]:
|
|
274
270
|
_reject_pure("claude", mode, pure, supported=True)
|
|
275
271
|
if pure or output_schema is not None:
|
|
@@ -342,6 +338,8 @@ def build_claude_argv(
|
|
|
342
338
|
argv.extend(["--model", model])
|
|
343
339
|
if reasoning_effort is not None:
|
|
344
340
|
argv.extend(["--effort", reasoning_effort])
|
|
341
|
+
if persona_file:
|
|
342
|
+
argv.extend(["--append-system-prompt-file", PERSONA_FILE_ARG_PLACEHOLDER])
|
|
345
343
|
return argv
|
|
346
344
|
|
|
347
345
|
|
|
@@ -18,6 +18,7 @@ from delegate_agent import (
|
|
|
18
18
|
config_commands,
|
|
19
19
|
harness_discovery,
|
|
20
20
|
inspection_commands,
|
|
21
|
+
personas,
|
|
21
22
|
profile_commands,
|
|
22
23
|
profile_guard,
|
|
23
24
|
profiles,
|
|
@@ -93,6 +94,7 @@ from delegate_agent.prompt_transport import ( # noqa: F401 # CURSOR_PROMPT_RED
|
|
|
93
94
|
DEVIN_AGENT_CONFIG_DISPLAY,
|
|
94
95
|
DROID_PROMPT_FILE_ARG_PLACEHOLDER,
|
|
95
96
|
DROID_PROMPT_FILE_DISPLAY,
|
|
97
|
+
PERSONA_FILE_ARG_PLACEHOLDER,
|
|
96
98
|
PROMPT_FILE_ARG_PLACEHOLDER,
|
|
97
99
|
PROMPT_FILE_DISPLAY,
|
|
98
100
|
PROMPT_TRANSPORT_ARGV,
|
|
@@ -291,6 +293,25 @@ def emit_config_command(parsed: ParsedCommand, stdout: TextIO) -> int:
|
|
|
291
293
|
return config_commands.emit(command, stdout)
|
|
292
294
|
|
|
293
295
|
|
|
296
|
+
def emit_personas(workspace: ResolvedWorkspace, *, json_mode: bool, stdout: TextIO) -> int:
|
|
297
|
+
rows = personas.list_personas(workspace.path)
|
|
298
|
+
if json_mode:
|
|
299
|
+
delegate_rendering.print_json({"schema": "delegate.personas.v1", "personas": rows}, stdout)
|
|
300
|
+
return EXIT_OK
|
|
301
|
+
if not rows:
|
|
302
|
+
print("No personas found.", file=stdout)
|
|
303
|
+
return EXIT_OK
|
|
304
|
+
for row in rows:
|
|
305
|
+
name = row.get("name", "")
|
|
306
|
+
source = row.get("source", "")
|
|
307
|
+
if "invalid" in row:
|
|
308
|
+
print(f"{name} ({source}): invalid: {row['invalid']}", file=stdout)
|
|
309
|
+
continue
|
|
310
|
+
shadow = " [shadows global]" if row.get("shadowsGlobal") else ""
|
|
311
|
+
print(f"{name} ({source}, {row.get('sizeBytes', 0)} bytes){shadow}", file=stdout)
|
|
312
|
+
return EXIT_OK
|
|
313
|
+
|
|
314
|
+
|
|
294
315
|
def dry_run_payload(request: Request) -> JsonObject:
|
|
295
316
|
payload: JsonObject = {
|
|
296
317
|
"ok": True,
|
|
@@ -328,6 +349,12 @@ def dry_run_payload(request: Request) -> JsonObject:
|
|
|
328
349
|
payload["group"] = request.group
|
|
329
350
|
if request.agent is not None:
|
|
330
351
|
payload["agent"] = request.agent
|
|
352
|
+
if request.persona_name is not None:
|
|
353
|
+
payload["personaName"] = request.persona_name
|
|
354
|
+
payload["personaSource"] = request.persona_source
|
|
355
|
+
payload["personaTransport"] = request.persona_transport
|
|
356
|
+
payload["personaDigest"] = request.persona_digest
|
|
357
|
+
payload["personaFile"] = request.persona_file
|
|
331
358
|
if request.resumed_from is not None:
|
|
332
359
|
payload["resumedFrom"] = request.resumed_from
|
|
333
360
|
if request.auth_profile is not None:
|
|
@@ -602,6 +629,12 @@ def make_run_context(
|
|
|
602
629
|
output_schema_text=request.output_schema_record_text,
|
|
603
630
|
agent=request.agent,
|
|
604
631
|
resumed_from=request.resumed_from,
|
|
632
|
+
persona_name=request.persona_name,
|
|
633
|
+
persona_source=request.persona_source,
|
|
634
|
+
persona_transport=request.persona_transport,
|
|
635
|
+
persona_digest=request.persona_digest,
|
|
636
|
+
persona_file=request.persona_file,
|
|
637
|
+
persona_text=request.persona_text,
|
|
605
638
|
)
|
|
606
639
|
|
|
607
640
|
|
|
@@ -760,6 +793,10 @@ def _execute_attached_worktree(
|
|
|
760
793
|
run_registry.write_private_text(
|
|
761
794
|
run_path / run_registry.PROMPT_TXT_FILE, ctx_runner.source_prompt
|
|
762
795
|
)
|
|
796
|
+
if ctx_runner.persona_text is not None:
|
|
797
|
+
run_registry.write_private_text(
|
|
798
|
+
run_path / run_registry.PERSONA_TXT_FILE, ctx_runner.persona_text
|
|
799
|
+
)
|
|
763
800
|
delegate_runner.write_manifest(
|
|
764
801
|
run_path,
|
|
765
802
|
delegate_runner.build_manifest(ctx_runner, execution_request.display_argv),
|
|
@@ -808,6 +845,8 @@ def _execute_attached_worktree(
|
|
|
808
845
|
prompt_file_placeholder=PROMPT_FILE_ARG_PLACEHOLDER,
|
|
809
846
|
agent_config_text=execution_request.agent_config_text,
|
|
810
847
|
agent_config_placeholder=DEVIN_AGENT_CONFIG_ARG_PLACEHOLDER,
|
|
848
|
+
persona_file_text=execution_request.persona_file_text,
|
|
849
|
+
persona_file_placeholder=PERSONA_FILE_ARG_PLACEHOLDER,
|
|
811
850
|
output_schema_text=request.output_schema_text,
|
|
812
851
|
output_schema_path=request.output_schema,
|
|
813
852
|
manifest_argv=execution_request.display_argv,
|
|
@@ -894,6 +933,12 @@ def execute_request(
|
|
|
894
933
|
prompt_file_placeholder=PROMPT_FILE_ARG_PLACEHOLDER,
|
|
895
934
|
agent_config_text=request.agent_config_text,
|
|
896
935
|
agent_config_placeholder=DEVIN_AGENT_CONFIG_ARG_PLACEHOLDER,
|
|
936
|
+
persona_file_text=(
|
|
937
|
+
request.persona_text
|
|
938
|
+
if request.persona_transport == "native-file"
|
|
939
|
+
else None
|
|
940
|
+
),
|
|
941
|
+
persona_file_placeholder=PERSONA_FILE_ARG_PLACEHOLDER,
|
|
897
942
|
output_schema_text=request.output_schema_text,
|
|
898
943
|
output_schema_path=request.output_schema,
|
|
899
944
|
manifest_argv=public_argv(request),
|
|
@@ -1157,6 +1202,12 @@ def execute_request(
|
|
|
1157
1202
|
prompt_file_placeholder=PROMPT_FILE_ARG_PLACEHOLDER,
|
|
1158
1203
|
agent_config_text=isolated_request.agent_config_text,
|
|
1159
1204
|
agent_config_placeholder=DEVIN_AGENT_CONFIG_ARG_PLACEHOLDER,
|
|
1205
|
+
persona_file_text=(
|
|
1206
|
+
isolated_request.persona_text
|
|
1207
|
+
if isolated_request.persona_transport == "native-file"
|
|
1208
|
+
else None
|
|
1209
|
+
),
|
|
1210
|
+
persona_file_placeholder=PERSONA_FILE_ARG_PLACEHOLDER,
|
|
1160
1211
|
output_schema_text=isolated_request.output_schema_text,
|
|
1161
1212
|
output_schema_path=isolated_request.output_schema,
|
|
1162
1213
|
manifest_argv=public_argv(isolated_request),
|
|
@@ -1320,6 +1371,10 @@ def main(
|
|
|
1320
1371
|
config, source = load_config(workspace=config_workspace)
|
|
1321
1372
|
validate_config(config)
|
|
1322
1373
|
|
|
1374
|
+
if parsed.subcommand == "personas":
|
|
1375
|
+
workspace = resolve_workspace(global_options.cwd)
|
|
1376
|
+
return emit_personas(workspace, json_mode=global_options.json_mode, stdout=stdout)
|
|
1377
|
+
|
|
1323
1378
|
discovery_profile: profiles.ProfileResolution | None = None
|
|
1324
1379
|
discovery_snapshot: JsonObject | None = None
|
|
1325
1380
|
if parsed.subcommand in {"models", "capabilities"}:
|
|
@@ -1425,7 +1480,7 @@ def main(
|
|
|
1425
1480
|
# through the normal request build and execution path.
|
|
1426
1481
|
parsed = resume_plan.parsed
|
|
1427
1482
|
global_options = parsed.global_options
|
|
1428
|
-
request = request_from_parsed(parsed, config, stdin)
|
|
1483
|
+
request = request_from_parsed(parsed, config, stdin, stderr)
|
|
1429
1484
|
if resume_plan is not None:
|
|
1430
1485
|
request = resume_command.apply_resume_to_request(request, resume_plan)
|
|
1431
1486
|
if request.dry_run:
|
|
@@ -160,7 +160,7 @@ def parse_help_subcommand(rest: list[str], json_mode: bool) -> ParsedCommand:
|
|
|
160
160
|
return help_command(json_mode, topic)
|
|
161
161
|
|
|
162
162
|
|
|
163
|
-
SIMPLE_INSPECTION_SUBCOMMANDS = frozenset({"models", "describe", "agent-help"})
|
|
163
|
+
SIMPLE_INSPECTION_SUBCOMMANDS = frozenset({"models", "describe", "agent-help", "personas"})
|
|
164
164
|
INSPECTION_OPTION_SUBCOMMANDS = frozenset({"models", "describe"})
|
|
165
165
|
|
|
166
166
|
|
|
@@ -791,6 +791,9 @@ def parse_modeless_engine(
|
|
|
791
791
|
include_dirty,
|
|
792
792
|
model,
|
|
793
793
|
agent,
|
|
794
|
+
persona,
|
|
795
|
+
no_persona,
|
|
796
|
+
allow_repo_persona,
|
|
794
797
|
) = parse_prompt_tail(rest[1:], json_mode, isolation, command_prefix=[engine, mode])
|
|
795
798
|
if agent is not None and engine != "opencode":
|
|
796
799
|
raise DelegateError("unsupported_agent", "--agent is only supported by opencode.")
|
|
@@ -844,6 +847,9 @@ def parse_modeless_engine(
|
|
|
844
847
|
dry_run=dry_run,
|
|
845
848
|
model=model,
|
|
846
849
|
agent=agent,
|
|
850
|
+
persona=persona,
|
|
851
|
+
no_persona=no_persona,
|
|
852
|
+
allow_repo_persona=allow_repo_persona,
|
|
847
853
|
),
|
|
848
854
|
)
|
|
849
855
|
|
|
@@ -918,6 +924,9 @@ def parse_droid(
|
|
|
918
924
|
include_dirty,
|
|
919
925
|
model,
|
|
920
926
|
agent,
|
|
927
|
+
persona,
|
|
928
|
+
no_persona,
|
|
929
|
+
allow_repo_persona,
|
|
921
930
|
) = parse_prompt_tail(tail, json_mode, isolation, command_prefix=command_prefix)
|
|
922
931
|
if agent is not None:
|
|
923
932
|
raise DelegateError("unsupported_agent", "--agent is only supported by opencode.")
|
|
@@ -973,6 +982,9 @@ def parse_droid(
|
|
|
973
982
|
dry_run=dry_run,
|
|
974
983
|
model=model,
|
|
975
984
|
agent=agent,
|
|
985
|
+
persona=persona,
|
|
986
|
+
no_persona=no_persona,
|
|
987
|
+
allow_repo_persona=allow_repo_persona,
|
|
976
988
|
),
|
|
977
989
|
)
|
|
978
990
|
|
|
@@ -1060,6 +1072,9 @@ def parse_resume(
|
|
|
1060
1072
|
drop_output_schema = False
|
|
1061
1073
|
include_dirty = False
|
|
1062
1074
|
dry_run = False
|
|
1075
|
+
persona: str | None = None
|
|
1076
|
+
no_persona = False
|
|
1077
|
+
allow_repo_persona = False
|
|
1063
1078
|
handle: str | None = None
|
|
1064
1079
|
extra_parts: list[str] = []
|
|
1065
1080
|
i = 0
|
|
@@ -1140,6 +1155,38 @@ def parse_resume(
|
|
|
1140
1155
|
include_dirty = True
|
|
1141
1156
|
i += 1
|
|
1142
1157
|
continue
|
|
1158
|
+
if token == "--persona":
|
|
1159
|
+
if i + 1 >= len(rest):
|
|
1160
|
+
raise DelegateError("missing_persona", "--persona requires a non-empty name.")
|
|
1161
|
+
value = rest[i + 1]
|
|
1162
|
+
if not value.strip() or value.startswith("-") or command_help.is_help_token(value):
|
|
1163
|
+
raise DelegateError("missing_persona", "--persona requires a non-empty name.")
|
|
1164
|
+
if persona is not None or no_persona:
|
|
1165
|
+
raise DelegateError(
|
|
1166
|
+
"invalid_option_combination",
|
|
1167
|
+
"--persona and --no-persona cannot be combined.",
|
|
1168
|
+
)
|
|
1169
|
+
persona = value
|
|
1170
|
+
i += 2
|
|
1171
|
+
continue
|
|
1172
|
+
if token == "--no-persona":
|
|
1173
|
+
if persona is not None or no_persona:
|
|
1174
|
+
raise DelegateError(
|
|
1175
|
+
"invalid_option_combination",
|
|
1176
|
+
"--persona and --no-persona cannot be combined.",
|
|
1177
|
+
)
|
|
1178
|
+
no_persona = True
|
|
1179
|
+
i += 1
|
|
1180
|
+
continue
|
|
1181
|
+
if token == "--allow-repo-persona":
|
|
1182
|
+
if allow_repo_persona:
|
|
1183
|
+
raise DelegateError(
|
|
1184
|
+
"invalid_option_combination",
|
|
1185
|
+
"Only one --allow-repo-persona flag is allowed.",
|
|
1186
|
+
)
|
|
1187
|
+
allow_repo_persona = True
|
|
1188
|
+
i += 1
|
|
1189
|
+
continue
|
|
1143
1190
|
if token == "--dry-run":
|
|
1144
1191
|
dry_run = True
|
|
1145
1192
|
i += 1
|
|
@@ -1183,6 +1230,9 @@ def parse_resume(
|
|
|
1183
1230
|
drop_output_schema=drop_output_schema,
|
|
1184
1231
|
include_dirty=include_dirty,
|
|
1185
1232
|
dry_run=dry_run,
|
|
1233
|
+
persona=persona,
|
|
1234
|
+
no_persona=no_persona,
|
|
1235
|
+
allow_repo_persona=allow_repo_persona,
|
|
1186
1236
|
),
|
|
1187
1237
|
)
|
|
1188
1238
|
|
|
@@ -1209,6 +1259,9 @@ def parse_prompt_tail(
|
|
|
1209
1259
|
bool,
|
|
1210
1260
|
str | None,
|
|
1211
1261
|
str | None,
|
|
1262
|
+
str | None,
|
|
1263
|
+
bool,
|
|
1264
|
+
bool,
|
|
1212
1265
|
]:
|
|
1213
1266
|
prompt_file: str | None = None
|
|
1214
1267
|
output_schema: str | None = None
|
|
@@ -1222,6 +1275,9 @@ def parse_prompt_tail(
|
|
|
1222
1275
|
timeout: int | None = None
|
|
1223
1276
|
model: str | None = None
|
|
1224
1277
|
agent: str | None = None
|
|
1278
|
+
persona: str | None = None
|
|
1279
|
+
no_persona = False
|
|
1280
|
+
allow_repo_persona = False
|
|
1225
1281
|
prompt_parts: list[str] = []
|
|
1226
1282
|
i = 0
|
|
1227
1283
|
while i < len(rest):
|
|
@@ -1354,6 +1410,49 @@ def parse_prompt_tail(
|
|
|
1354
1410
|
agent = value
|
|
1355
1411
|
i += 2
|
|
1356
1412
|
continue
|
|
1413
|
+
if token == "--persona":
|
|
1414
|
+
if prompt_parts:
|
|
1415
|
+
raise DelegateError(
|
|
1416
|
+
"ambiguous_persona_source", "--persona must appear before direct prompt text."
|
|
1417
|
+
)
|
|
1418
|
+
if i + 1 >= len(rest):
|
|
1419
|
+
raise DelegateError("missing_persona", "--persona requires a non-empty name.")
|
|
1420
|
+
value = rest[i + 1]
|
|
1421
|
+
if not value.strip() or value.startswith("-") or command_help.is_help_token(value):
|
|
1422
|
+
raise DelegateError("missing_persona", "--persona requires a non-empty name.")
|
|
1423
|
+
if persona is not None or no_persona:
|
|
1424
|
+
raise DelegateError(
|
|
1425
|
+
"invalid_option_combination", "--persona and --no-persona cannot be combined."
|
|
1426
|
+
)
|
|
1427
|
+
persona = value
|
|
1428
|
+
i += 2
|
|
1429
|
+
continue
|
|
1430
|
+
if token == "--no-persona":
|
|
1431
|
+
if prompt_parts:
|
|
1432
|
+
raise DelegateError(
|
|
1433
|
+
"ambiguous_persona_source",
|
|
1434
|
+
"--no-persona must appear before direct prompt text.",
|
|
1435
|
+
)
|
|
1436
|
+
if persona is not None or no_persona:
|
|
1437
|
+
raise DelegateError(
|
|
1438
|
+
"invalid_option_combination", "--persona and --no-persona cannot be combined."
|
|
1439
|
+
)
|
|
1440
|
+
no_persona = True
|
|
1441
|
+
i += 1
|
|
1442
|
+
continue
|
|
1443
|
+
if token == "--allow-repo-persona":
|
|
1444
|
+
if prompt_parts:
|
|
1445
|
+
raise DelegateError(
|
|
1446
|
+
"ambiguous_persona_source",
|
|
1447
|
+
"--allow-repo-persona must appear before direct prompt text.",
|
|
1448
|
+
)
|
|
1449
|
+
if allow_repo_persona:
|
|
1450
|
+
raise DelegateError(
|
|
1451
|
+
"invalid_option_combination", "Only one --allow-repo-persona flag is allowed."
|
|
1452
|
+
)
|
|
1453
|
+
allow_repo_persona = True
|
|
1454
|
+
i += 1
|
|
1455
|
+
continue
|
|
1357
1456
|
if token == "--progress":
|
|
1358
1457
|
if progress_intent == "on":
|
|
1359
1458
|
raise DelegateError(
|
|
@@ -1476,6 +1575,9 @@ def parse_prompt_tail(
|
|
|
1476
1575
|
include_dirty,
|
|
1477
1576
|
model,
|
|
1478
1577
|
agent,
|
|
1578
|
+
persona,
|
|
1579
|
+
no_persona,
|
|
1580
|
+
allow_repo_persona,
|
|
1479
1581
|
)
|
|
1480
1582
|
|
|
1481
1583
|
|