@pushpalsdev/cli 1.0.18 → 1.0.20
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/dist/pushpals-cli.js +291 -44
- package/package.json +1 -1
- package/runtime/configs/backend.toml +1 -1
- package/runtime/configs/default.toml +1 -1
- package/runtime/sandbox/apps/workerpals/.python-version +1 -0
- package/runtime/sandbox/apps/workerpals/Dockerfile.sandbox +71 -0
- package/runtime/sandbox/apps/workerpals/package.json +25 -0
- package/runtime/sandbox/apps/workerpals/pyproject.toml +8 -0
- package/runtime/sandbox/apps/workerpals/src/backends/backend_config.ts +119 -0
- package/runtime/sandbox/apps/workerpals/src/backends/miniswe/miniswe_executor.py +2029 -0
- package/runtime/sandbox/apps/workerpals/src/backends/miniswe_backend.ts +48 -0
- package/runtime/sandbox/apps/workerpals/src/backends/openai_codex/openai_codex_executor.py +1259 -0
- package/runtime/sandbox/apps/workerpals/src/backends/openai_codex/test_openai_codex_runtime_config.py +110 -0
- package/runtime/sandbox/apps/workerpals/src/backends/openai_codex_backend.ts +67 -0
- package/runtime/sandbox/apps/workerpals/src/backends/openhands/openhands_executor.py +563 -0
- package/runtime/sandbox/apps/workerpals/src/backends/openhands_backend.ts +161 -0
- package/runtime/sandbox/apps/workerpals/src/backends/openhands_task_execute.ts +536 -0
- package/runtime/sandbox/apps/workerpals/src/backends/shared/executor_base.py +746 -0
- package/runtime/sandbox/apps/workerpals/src/backends/shared/test_settings_resolver.py +60 -0
- package/runtime/sandbox/apps/workerpals/src/backends/task_execute_registry.ts +21 -0
- package/runtime/sandbox/apps/workerpals/src/backends/types.ts +52 -0
- package/runtime/sandbox/apps/workerpals/src/common/execution_utils.ts +149 -0
- package/runtime/sandbox/apps/workerpals/src/common/executor_backend.ts +15 -0
- package/runtime/sandbox/apps/workerpals/src/common/generic_python_executor.ts +210 -0
- package/runtime/sandbox/apps/workerpals/src/common/logger.ts +65 -0
- package/runtime/sandbox/apps/workerpals/src/common/types.ts +9 -0
- package/runtime/sandbox/apps/workerpals/src/common/worktree_cleanup.ts +66 -0
- package/runtime/sandbox/apps/workerpals/src/context_manager.ts +45 -0
- package/runtime/sandbox/apps/workerpals/src/docker_executor.ts +1842 -0
- package/runtime/sandbox/apps/workerpals/src/execute_job.ts +3063 -0
- package/runtime/sandbox/apps/workerpals/src/job_runner.ts +194 -0
- package/runtime/sandbox/apps/workerpals/src/shell_manager.ts +210 -0
- package/runtime/sandbox/apps/workerpals/src/timeout_policy.ts +24 -0
- package/runtime/sandbox/apps/workerpals/src/workerpals_main.ts +1436 -0
- package/runtime/sandbox/apps/workerpals/tsconfig.json +15 -0
- package/runtime/sandbox/apps/workerpals/uv.lock +2014 -0
- package/runtime/sandbox/bun.lock +2591 -0
- package/runtime/sandbox/configs/backend.toml +79 -0
- package/runtime/sandbox/configs/default.toml +260 -0
- package/runtime/sandbox/configs/dev.toml +2 -0
- package/runtime/sandbox/configs/local.example.toml +129 -0
- package/runtime/sandbox/package.json +65 -0
- package/runtime/sandbox/packages/protocol/README.md +168 -0
- package/runtime/sandbox/packages/protocol/package.json +37 -0
- package/runtime/sandbox/packages/protocol/scripts/copy-schemas.js +17 -0
- package/runtime/sandbox/packages/protocol/src/a2a/README.md +52 -0
- package/runtime/sandbox/packages/protocol/src/a2a/mapping.ts +55 -0
- package/runtime/sandbox/packages/protocol/src/index.browser.ts +25 -0
- package/runtime/sandbox/packages/protocol/src/index.ts +25 -0
- package/runtime/sandbox/packages/protocol/src/schemas/approvals.schema.json +6 -0
- package/runtime/sandbox/packages/protocol/src/schemas/envelope.schema.json +96 -0
- package/runtime/sandbox/packages/protocol/src/schemas/events.schema.json +679 -0
- package/runtime/sandbox/packages/protocol/src/schemas/http.schema.json +50 -0
- package/runtime/sandbox/packages/protocol/src/types.ts +267 -0
- package/runtime/sandbox/packages/protocol/src/validate.browser.ts +154 -0
- package/runtime/sandbox/packages/protocol/src/validate.ts +233 -0
- package/runtime/sandbox/packages/protocol/src/version.ts +1 -0
- package/runtime/sandbox/packages/protocol/tsconfig.json +20 -0
- package/runtime/sandbox/packages/shared/package.json +19 -0
- package/runtime/sandbox/packages/shared/src/autonomy_policy.ts +400 -0
- package/runtime/sandbox/packages/shared/src/client_preflight.ts +286 -0
- package/runtime/sandbox/packages/shared/src/communication.ts +313 -0
- package/runtime/sandbox/packages/shared/src/config.ts +2180 -0
- package/runtime/sandbox/packages/shared/src/config_template_parity.ts +70 -0
- package/runtime/sandbox/packages/shared/src/git_backend.ts +205 -0
- package/runtime/sandbox/packages/shared/src/index.ts +101 -0
- package/runtime/sandbox/packages/shared/src/local_network.ts +101 -0
- package/runtime/sandbox/packages/shared/src/localbuddy_runtime.ts +314 -0
- package/runtime/sandbox/packages/shared/src/prompts.ts +64 -0
- package/runtime/sandbox/packages/shared/src/repo.ts +134 -0
- package/runtime/sandbox/packages/shared/src/session_event_visibility.ts +25 -0
- package/runtime/sandbox/packages/shared/src/vision.ts +247 -0
- package/runtime/sandbox/packages/shared/tsconfig.json +16 -0
- package/runtime/sandbox/prompts/workerpals/codex_quality_critic_instruction_prompt.md +14 -0
- package/runtime/sandbox/prompts/workerpals/commit_message_prompt.md +36 -0
- package/runtime/sandbox/prompts/workerpals/commit_message_user_prompt.md +7 -0
- package/runtime/sandbox/prompts/workerpals/miniswe_broker_system_prompt.md +33 -0
- package/runtime/sandbox/prompts/workerpals/miniswe_broker_task_prompt.md +5 -0
- package/runtime/sandbox/prompts/workerpals/miniswe_completion_requirement.md +1 -0
- package/runtime/sandbox/prompts/workerpals/miniswe_context_compaction_retry_prompt.md +1 -0
- package/runtime/sandbox/prompts/workerpals/miniswe_explicit_targets_block.md +2 -0
- package/runtime/sandbox/prompts/workerpals/miniswe_recovery_guidance_base.md +4 -0
- package/runtime/sandbox/prompts/workerpals/miniswe_recovery_guidance_blocker_line.md +1 -0
- package/runtime/sandbox/prompts/workerpals/miniswe_strict_tool_use_guidance.md +6 -0
- package/runtime/sandbox/prompts/workerpals/miniswe_supplemental_guidance_section.md +2 -0
- package/runtime/sandbox/prompts/workerpals/miniswe_timeout_note.md +1 -0
- package/runtime/sandbox/prompts/workerpals/miniswe_toolcall_retry_guidance.md +1 -0
- package/runtime/sandbox/prompts/workerpals/openai_codex_default_system_prompt.md +4 -0
- package/runtime/sandbox/prompts/workerpals/openai_codex_instruction_wrapper.md +5 -0
- package/runtime/sandbox/prompts/workerpals/openai_codex_runtime_policy_appendix.md +5 -0
- package/runtime/sandbox/prompts/workerpals/openai_codex_supplemental_guidance_section.md +2 -0
- package/runtime/sandbox/prompts/workerpals/openai_codex_task_execute_system_prompt.md +12 -0
- package/runtime/sandbox/prompts/workerpals/openhands_minimal_security_policy.j2 +8 -0
- package/runtime/sandbox/prompts/workerpals/openhands_minimal_system_prompt.j2 +20 -0
- package/runtime/sandbox/prompts/workerpals/openhands_strict_tool_use_message.md +1 -0
- package/runtime/sandbox/prompts/workerpals/openhands_supplemental_guidance_message.md +2 -0
- package/runtime/sandbox/prompts/workerpals/openhands_task_execute_fallback_system_prompt.md +1 -0
- package/runtime/sandbox/prompts/workerpals/openhands_task_execute_system_prompt.md +21 -0
- package/runtime/sandbox/prompts/workerpals/openhands_task_user_prompt.md +6 -0
- package/runtime/sandbox/prompts/workerpals/openhands_timeout_note.md +1 -0
- package/runtime/sandbox/prompts/workerpals/pr_description.md +42 -0
- package/runtime/sandbox/prompts/workerpals/task_quality_critic_system_prompt.md +9 -0
- package/runtime/sandbox/prompts/workerpals/task_quality_critic_user_prompt.md +17 -0
- package/runtime/sandbox/prompts/workerpals/workerpals_system_prompt.md +115 -0
- package/runtime/sandbox/protocol/schemas/approvals.schema.json +6 -0
- package/runtime/sandbox/protocol/schemas/envelope.schema.json +96 -0
- package/runtime/sandbox/protocol/schemas/events.schema.json +679 -0
- package/runtime/sandbox/protocol/schemas/http.schema.json +50 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import unittest
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
_HERE = Path(__file__).resolve().parent
|
|
6
|
+
_SHARED = _HERE.parent / "shared"
|
|
7
|
+
for path in (_HERE, _SHARED):
|
|
8
|
+
if str(path) not in sys.path:
|
|
9
|
+
sys.path.insert(0, str(path))
|
|
10
|
+
|
|
11
|
+
from executor_base import SettingsResolver
|
|
12
|
+
from openai_codex_executor import (
|
|
13
|
+
OpenAICodexRuntimeConfig,
|
|
14
|
+
_build_instruction,
|
|
15
|
+
_detect_codex_workaround_signal,
|
|
16
|
+
_load_prompt_template,
|
|
17
|
+
_repo_root_for_prompt_loading,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class OpenAICodexRuntimeConfigTests(unittest.TestCase):
|
|
22
|
+
def test_env_overrides_config_for_selected_fields(self) -> None:
|
|
23
|
+
resolver = SettingsResolver(
|
|
24
|
+
env={
|
|
25
|
+
"PUSHPALS_OPENAI_CODEX_BIN": "bunx --yes @openai/codex",
|
|
26
|
+
"PUSHPALS_OPENAI_CODEX_AUTH_MODE": "chatgpt",
|
|
27
|
+
"WORKERPALS_OPENAI_CODEX_JSON": "false",
|
|
28
|
+
},
|
|
29
|
+
config_loader=lambda: {
|
|
30
|
+
"workerpals": {
|
|
31
|
+
"openai_codex": {
|
|
32
|
+
"bin": "codex",
|
|
33
|
+
"auth_mode": "api_key",
|
|
34
|
+
"json": True,
|
|
35
|
+
"sandbox": "workspace-write",
|
|
36
|
+
},
|
|
37
|
+
"llm": {
|
|
38
|
+
"reasoning_effort": "medium",
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
)
|
|
43
|
+
cfg = OpenAICodexRuntimeConfig.from_sources(resolver)
|
|
44
|
+
self.assertEqual(cfg.codex_bin, "bunx --yes @openai/codex")
|
|
45
|
+
self.assertEqual(cfg.auth_mode, "chatgpt")
|
|
46
|
+
self.assertFalse(cfg.json_output)
|
|
47
|
+
self.assertEqual(cfg.reasoning_effort, "medium")
|
|
48
|
+
self.assertEqual(cfg.sandbox, "workspace-write")
|
|
49
|
+
|
|
50
|
+
def test_defaults_apply_when_missing(self) -> None:
|
|
51
|
+
cfg = OpenAICodexRuntimeConfig.from_sources(
|
|
52
|
+
SettingsResolver(env={}, config_loader=lambda: {}),
|
|
53
|
+
)
|
|
54
|
+
self.assertEqual(cfg.auth_mode, "auto")
|
|
55
|
+
self.assertEqual(cfg.approval_policy, "never")
|
|
56
|
+
self.assertEqual(cfg.sandbox, "workspace-write")
|
|
57
|
+
self.assertEqual(cfg.color, "never")
|
|
58
|
+
self.assertFalse(cfg.json_output)
|
|
59
|
+
|
|
60
|
+
def test_build_instruction_includes_codex_runtime_invariants(self) -> None:
|
|
61
|
+
prompt = _build_instruction("Add two tests for localbuddy", [])
|
|
62
|
+
self.assertIn("Codex CLI is required infrastructure", prompt)
|
|
63
|
+
self.assertIn("Runtime policy guardrails (mandatory):", prompt)
|
|
64
|
+
self.assertIn("Canonical task instruction", prompt)
|
|
65
|
+
self.assertIn("Add two tests for localbuddy", prompt)
|
|
66
|
+
|
|
67
|
+
def test_build_instruction_appends_supplemental_guidance(self) -> None:
|
|
68
|
+
prompt = _build_instruction(
|
|
69
|
+
"Fix flaky request-status tests",
|
|
70
|
+
["Keep assertions strict", "Run bun test tests/localbuddy.request-status.test.ts"],
|
|
71
|
+
)
|
|
72
|
+
self.assertIn("Supplemental execution guidance", prompt)
|
|
73
|
+
self.assertIn("Keep assertions strict", prompt)
|
|
74
|
+
self.assertIn("bun test tests/localbuddy.request-status.test.ts", prompt)
|
|
75
|
+
|
|
76
|
+
def test_detects_codex_workaround_signals(self) -> None:
|
|
77
|
+
signal = _detect_codex_workaround_signal(
|
|
78
|
+
"Adapting test to avoid external Codex calls because Codex CLI isn't available in this environment.",
|
|
79
|
+
)
|
|
80
|
+
self.assertIsNotNone(signal)
|
|
81
|
+
|
|
82
|
+
def test_detects_explicit_fallback_language(self) -> None:
|
|
83
|
+
signal = _detect_codex_workaround_signal(
|
|
84
|
+
"Codex CLI isn't available, so I switched to a fallback and continued with edits.",
|
|
85
|
+
)
|
|
86
|
+
self.assertIsNotNone(signal)
|
|
87
|
+
|
|
88
|
+
def test_ignores_normal_codex_status_messages(self) -> None:
|
|
89
|
+
signal = _detect_codex_workaround_signal(
|
|
90
|
+
"Codex CLI login status is ready and task execution can proceed.",
|
|
91
|
+
)
|
|
92
|
+
self.assertIsNone(signal)
|
|
93
|
+
|
|
94
|
+
def test_ignores_policy_instruction_text(self) -> None:
|
|
95
|
+
signal = _detect_codex_workaround_signal(
|
|
96
|
+
"If Codex CLI auth/execution is unavailable, fail loudly with a clear error and stop; do not apply non-Codex workarounds.",
|
|
97
|
+
)
|
|
98
|
+
self.assertIsNone(signal)
|
|
99
|
+
|
|
100
|
+
def test_discovers_repo_root_for_prompt_loading(self) -> None:
|
|
101
|
+
repo_root = _repo_root_for_prompt_loading()
|
|
102
|
+
self.assertTrue((repo_root / "prompts").is_dir())
|
|
103
|
+
|
|
104
|
+
def test_loads_openai_codex_task_prompt_template(self) -> None:
|
|
105
|
+
template = _load_prompt_template("workerpals/openai_codex_task_execute_system_prompt.md")
|
|
106
|
+
self.assertIn("Codex CLI is required infrastructure", template)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
if __name__ == "__main__":
|
|
110
|
+
unittest.main()
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { resolve } from "path";
|
|
2
|
+
import type { DockerBackendSpec } from "./types.js";
|
|
3
|
+
import { createGenericPythonExecutor } from "../common/generic_python_executor.js";
|
|
4
|
+
|
|
5
|
+
function normalizeContainerPython(configuredPython: string, sharedVenvPython: string): string {
|
|
6
|
+
const configured = configuredPython.trim();
|
|
7
|
+
if (!configured) {
|
|
8
|
+
return sharedVenvPython;
|
|
9
|
+
}
|
|
10
|
+
const lowered = configured.toLowerCase();
|
|
11
|
+
if (
|
|
12
|
+
lowered === "python" ||
|
|
13
|
+
lowered === "python3" ||
|
|
14
|
+
configured.includes("\\") ||
|
|
15
|
+
/^[a-zA-Z]:/.test(configured) ||
|
|
16
|
+
configured.startsWith(".")
|
|
17
|
+
) {
|
|
18
|
+
return sharedVenvPython;
|
|
19
|
+
}
|
|
20
|
+
return configured;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function warmupProbeCommand(sharedVenvPython: string): string {
|
|
24
|
+
return (
|
|
25
|
+
`PY="\${PUSHPALS_OPENAI_CODEX_PYTHON:-${sharedVenvPython}}"; ` +
|
|
26
|
+
'AUTH_MODE_RAW="${PUSHPALS_OPENAI_CODEX_AUTH_MODE:-auto}"; ' +
|
|
27
|
+
'AUTH_MODE="$(printf %s "$AUTH_MODE_RAW" | tr "[:upper:]" "[:lower:]")"; ' +
|
|
28
|
+
'if [ ! -x "$PY" ]; then PY="$(command -v python3 || command -v python || true)"; fi; ' +
|
|
29
|
+
'[ -n "$PY" ] || { echo "python runtime not found" >&2; exit 1; }; ' +
|
|
30
|
+
'if command -v bunx >/dev/null 2>&1; then ' +
|
|
31
|
+
' CODEX_CMD="bunx --yes @openai/codex"; ' +
|
|
32
|
+
'elif command -v codex >/dev/null 2>&1; then ' +
|
|
33
|
+
' CODEX_CMD="codex"; ' +
|
|
34
|
+
'else ' +
|
|
35
|
+
' echo "Neither bunx nor codex was found in PATH" >&2; ' +
|
|
36
|
+
" exit 1; " +
|
|
37
|
+
'fi; ' +
|
|
38
|
+
'sh -lc "$CODEX_CMD --version"; ' +
|
|
39
|
+
'NEED_LOGIN="0"; ' +
|
|
40
|
+
'if [ "$AUTH_MODE" = "chatgpt" ] || [ "$AUTH_MODE" = "chatgpt_login" ] || [ "$AUTH_MODE" = "subscription" ]; then NEED_LOGIN="1"; fi; ' +
|
|
41
|
+
'if [ "$AUTH_MODE" = "auto" ] && [ -z "${OPENAI_API_KEY:-}" ]; then NEED_LOGIN="1"; fi; ' +
|
|
42
|
+
'if [ "$NEED_LOGIN" = "1" ]; then ' +
|
|
43
|
+
' sh -lc "$CODEX_CMD login status" >/dev/null 2>&1 || { ' +
|
|
44
|
+
' echo "Codex CLI login is required for PUSHPALS_OPENAI_CODEX_AUTH_MODE=${AUTH_MODE}. Run codex login (or bunx --yes @openai/codex login)." >&2; ' +
|
|
45
|
+
" exit 1; " +
|
|
46
|
+
" }; " +
|
|
47
|
+
"fi"
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const OPENAI_CODEX_BACKEND: DockerBackendSpec = {
|
|
52
|
+
name: "openai_codex",
|
|
53
|
+
configuredPython: (config) => config.openai_codex?.python ?? "python",
|
|
54
|
+
timeoutMs: (config) => config.openai_codex?.timeoutMs ?? 300_000,
|
|
55
|
+
normalizeContainerPython,
|
|
56
|
+
warmContainerStartupCommand: () => "tail -f /dev/null",
|
|
57
|
+
warmContainerEnv: () => ({}),
|
|
58
|
+
ensureWarmRuntime: null,
|
|
59
|
+
diagnosticChecks: () => [],
|
|
60
|
+
warmupProbeCommand,
|
|
61
|
+
taskExecute: createGenericPythonExecutor({
|
|
62
|
+
backendName: "openai_codex",
|
|
63
|
+
scriptPath: resolve(import.meta.dir, "openai_codex", "openai_codex_executor.py"),
|
|
64
|
+
pythonConfigKey: "openaiCodexPython",
|
|
65
|
+
timeoutConfigKey: "openaiCodexTimeoutMs",
|
|
66
|
+
}),
|
|
67
|
+
};
|