Refactor devcontainer and MCP tools for containerized development
Ajout et configuration d’un environnement de développement conteneurisé (devcontainer) avec support multi-langages (Go, Rust, Python), intégration d’outils LLM locaux/cloud (LM Studio, Claude Pro), et refonte des outils MCP : suppression du module sandbox, correction de la gestion des chemins projet dans jj.py, ajout d’une fonction jj_new_tool, et structuration du Makefile pour le build multiplateforme. Mise à jour des scripts (docker-entrypoint.sh, setup-devcontainer.sh), du README.md et de bin/jj-ai-commit.sh pour automatiser la génération de messages de commit à partir des résumés des fichiers modifiés.
This commit is contained in:
0
.builder-ready
Normal file
0
.builder-ready
Normal file
95
.claude-devcontainer/.claude.json
Normal file
95
.claude-devcontainer/.claude.json
Normal file
@@ -0,0 +1,95 @@
|
||||
{
|
||||
"cachedGrowthBookFeatures": {
|
||||
"tengu_claudeai_mcp_connectors": true,
|
||||
"tengu_event_sampling_config": {},
|
||||
"tengu_frond_boric": {},
|
||||
"tengu_log_segment_events": false,
|
||||
"tengu_log_datadog_events": true,
|
||||
"tengu_marble_anvil": true,
|
||||
"tengu_tool_pear": false,
|
||||
"tengu_scarf_coffee": false,
|
||||
"tengu_herring_clock": false,
|
||||
"tengu_keybinding_customization_release": true,
|
||||
"tengu_marble_whisper": true,
|
||||
"tengu_amber_quartz": false,
|
||||
"tengu_thinkback": false,
|
||||
"tengu_cicada_nap_ms": 0,
|
||||
"tengu_miraculo_the_bard": false,
|
||||
"tengu_miraculo_the_bard2": false,
|
||||
"tengu_paper_halyard": false,
|
||||
"tengu_chomp_inflection": false,
|
||||
"tengu_marble_sandcastle": true,
|
||||
"tengu_desktop_upsell": {
|
||||
"enable_shortcut_tip": false,
|
||||
"enable_startup_dialog": false
|
||||
},
|
||||
"tengu_marble_lantern_disabled": false,
|
||||
"tengu_pid_based_version_locking": true,
|
||||
"tengu_mcp_elicitation": false,
|
||||
"tengu_kairos_cron": true,
|
||||
"tengu_pebble_leaf_prune": false,
|
||||
"tengu_swinburne_dune": false,
|
||||
"tengu_coral_fern": false,
|
||||
"tengu_basalt_3kr": false,
|
||||
"tengu_summarize_tool_results": true,
|
||||
"tengu_bergotte_lantern": false,
|
||||
"tengu_sotto_voce": true,
|
||||
"tengu_system_prompt_global_cache": true,
|
||||
"tengu_turtle_carbon": true,
|
||||
"tengu_glacier_2xr": false,
|
||||
"enhanced_telemetry_beta": false,
|
||||
"tengu_streaming_tool_execution2": true,
|
||||
"tengu_moth_copse": false,
|
||||
"tengu_tool_search_unsupported_models": [
|
||||
"haiku"
|
||||
],
|
||||
"tengu_defer_all_bn4": false,
|
||||
"tengu_fgts": false,
|
||||
"tengu_tst_hint_m7r": false,
|
||||
"tengu_attribution_header": true,
|
||||
"tengu_prompt_cache_1h_config": {
|
||||
"allowlist": [
|
||||
"repl_main_thread*",
|
||||
"sdk",
|
||||
"auto_mode"
|
||||
]
|
||||
},
|
||||
"tengu_disable_streaming_to_non_streaming_fallback": false,
|
||||
"tengu_tool_input_aliasing": false,
|
||||
"tengu_satin_quoll": {},
|
||||
"tengu_amber_prism": false,
|
||||
"tengu_tight_weave": true,
|
||||
"tengu_auto_background_agents": false
|
||||
},
|
||||
"firstStartTime": "2026-03-11T12:56:06.706Z",
|
||||
"opusProMigrationComplete": true,
|
||||
"sonnet1m45MigrationComplete": true,
|
||||
"userID": "2525622ce171b408689c31f61f66ba3433629fa13b0656ed565073ba5f6dc2c6",
|
||||
"clientDataCache": {
|
||||
"data": {},
|
||||
"timestamp": 1773233813304
|
||||
},
|
||||
"changelogLastFetched": 1773233777137,
|
||||
"oauthAccount": {
|
||||
"accountUuid": "f093e810-c7e5-4d6b-902b-ec1fa73cbc94",
|
||||
"emailAddress": "eric.coissac@gmail.com",
|
||||
"organizationUuid": "c5e61747-337f-4fed-bf22-ca9925e92650",
|
||||
"hasExtraUsageEnabled": true,
|
||||
"billingType": "stripe_subscription",
|
||||
"accountCreatedAt": "2025-07-29T14:22:00.696404Z",
|
||||
"subscriptionCreatedAt": "2025-10-02T16:14:05.694173Z",
|
||||
"displayName": "Eric",
|
||||
"organizationRole": "admin",
|
||||
"workspaceRole": null,
|
||||
"organizationName": "eric.coissac@gmail.com's Organization"
|
||||
},
|
||||
"claudeCodeFirstTokenDate": "2025-10-05T14:58:34.301962Z",
|
||||
"penguinModeOrgEnabled": true,
|
||||
"groveConfigCache": {
|
||||
"f093e810-c7e5-4d6b-902b-ec1fa73cbc94": {
|
||||
"grove_enabled": true,
|
||||
"timestamp": 1773233813326
|
||||
}
|
||||
},
|
||||
"cachedExtraUsageDisabledReason": "out_of_credits"
|
||||
}
|
||||
1
.claude-devcontainer/.credentials.json
Normal file
1
.claude-devcontainer/.credentials.json
Normal file
@@ -0,0 +1 @@
|
||||
{"claudeAiOauth":{"accessToken":"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","refreshToken":"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","expiresAt":1773262609887,"scopes":["user:inference","user:mcp_servers","user:profile","user:sessions:claude_code"],"subscriptionType":"pro","rateLimitTier":"default_claude_ai"}}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"firstStartTime": "2026-03-11T12:56:06.706Z"
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"cachedGrowthBookFeatures": {
|
||||
"tengu_claudeai_mcp_connectors": true,
|
||||
"tengu_event_sampling_config": {},
|
||||
"tengu_frond_boric": {},
|
||||
"tengu_log_segment_events": false,
|
||||
"tengu_log_datadog_events": true,
|
||||
"tengu_marble_anvil": true,
|
||||
"tengu_tool_pear": false,
|
||||
"tengu_scarf_coffee": false,
|
||||
"tengu_herring_clock": false,
|
||||
"tengu_keybinding_customization_release": true,
|
||||
"tengu_marble_whisper": true,
|
||||
"tengu_amber_quartz": false,
|
||||
"tengu_thinkback": false,
|
||||
"tengu_cicada_nap_ms": 0,
|
||||
"tengu_miraculo_the_bard": false,
|
||||
"tengu_miraculo_the_bard2": false,
|
||||
"tengu_paper_halyard": false,
|
||||
"tengu_chomp_inflection": false,
|
||||
"tengu_marble_sandcastle": true,
|
||||
"tengu_desktop_upsell": {
|
||||
"enable_shortcut_tip": false,
|
||||
"enable_startup_dialog": false
|
||||
},
|
||||
"tengu_marble_lantern_disabled": false
|
||||
},
|
||||
"firstStartTime": "2026-03-11T12:56:06.706Z",
|
||||
"opusProMigrationComplete": true,
|
||||
"sonnet1m45MigrationComplete": true,
|
||||
"userID": "2525622ce171b408689c31f61f66ba3433629fa13b0656ed565073ba5f6dc2c6",
|
||||
"clientDataCache": {
|
||||
"data": {},
|
||||
"timestamp": 1773233813304
|
||||
},
|
||||
"changelogLastFetched": 1773233777137,
|
||||
"oauthAccount": {
|
||||
"accountUuid": "f093e810-c7e5-4d6b-902b-ec1fa73cbc94",
|
||||
"emailAddress": "eric.coissac@gmail.com",
|
||||
"organizationUuid": "c5e61747-337f-4fed-bf22-ca9925e92650",
|
||||
"hasExtraUsageEnabled": true,
|
||||
"billingType": "stripe_subscription",
|
||||
"accountCreatedAt": "2025-07-29T14:22:00.696404Z",
|
||||
"subscriptionCreatedAt": "2025-10-02T16:14:05.694173Z",
|
||||
"displayName": "Eric",
|
||||
"organizationRole": "admin",
|
||||
"workspaceRole": null,
|
||||
"organizationName": "eric.coissac@gmail.com's Organization"
|
||||
},
|
||||
"claudeCodeFirstTokenDate": "2025-10-05T14:58:34.301962Z",
|
||||
"penguinModeOrgEnabled": true,
|
||||
"groveConfigCache": {
|
||||
"f093e810-c7e5-4d6b-902b-ec1fa73cbc94": {
|
||||
"grove_enabled": true,
|
||||
"timestamp": 1773233813326
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"cachedGrowthBookFeatures": {
|
||||
"tengu_claudeai_mcp_connectors": true,
|
||||
"tengu_event_sampling_config": {},
|
||||
"tengu_frond_boric": {},
|
||||
"tengu_log_segment_events": false,
|
||||
"tengu_log_datadog_events": true,
|
||||
"tengu_marble_anvil": true,
|
||||
"tengu_tool_pear": false,
|
||||
"tengu_scarf_coffee": false,
|
||||
"tengu_herring_clock": false,
|
||||
"tengu_keybinding_customization_release": true,
|
||||
"tengu_marble_whisper": true,
|
||||
"tengu_amber_quartz": false,
|
||||
"tengu_thinkback": false,
|
||||
"tengu_cicada_nap_ms": 0,
|
||||
"tengu_miraculo_the_bard": false,
|
||||
"tengu_miraculo_the_bard2": false,
|
||||
"tengu_paper_halyard": false,
|
||||
"tengu_chomp_inflection": false,
|
||||
"tengu_marble_sandcastle": true,
|
||||
"tengu_desktop_upsell": {
|
||||
"enable_shortcut_tip": false,
|
||||
"enable_startup_dialog": false
|
||||
},
|
||||
"tengu_marble_lantern_disabled": false,
|
||||
"tengu_pid_based_version_locking": true
|
||||
},
|
||||
"firstStartTime": "2026-03-11T12:56:06.706Z",
|
||||
"opusProMigrationComplete": true,
|
||||
"sonnet1m45MigrationComplete": true,
|
||||
"userID": "2525622ce171b408689c31f61f66ba3433629fa13b0656ed565073ba5f6dc2c6",
|
||||
"clientDataCache": {
|
||||
"data": {},
|
||||
"timestamp": 1773233813304
|
||||
},
|
||||
"changelogLastFetched": 1773233777137,
|
||||
"oauthAccount": {
|
||||
"accountUuid": "f093e810-c7e5-4d6b-902b-ec1fa73cbc94",
|
||||
"emailAddress": "eric.coissac@gmail.com",
|
||||
"organizationUuid": "c5e61747-337f-4fed-bf22-ca9925e92650",
|
||||
"hasExtraUsageEnabled": true,
|
||||
"billingType": "stripe_subscription",
|
||||
"accountCreatedAt": "2025-07-29T14:22:00.696404Z",
|
||||
"subscriptionCreatedAt": "2025-10-02T16:14:05.694173Z",
|
||||
"displayName": "Eric",
|
||||
"organizationRole": "admin",
|
||||
"workspaceRole": null,
|
||||
"organizationName": "eric.coissac@gmail.com's Organization"
|
||||
},
|
||||
"claudeCodeFirstTokenDate": "2025-10-05T14:58:34.301962Z",
|
||||
"penguinModeOrgEnabled": true,
|
||||
"groveConfigCache": {
|
||||
"f093e810-c7e5-4d6b-902b-ec1fa73cbc94": {
|
||||
"grove_enabled": true,
|
||||
"timestamp": 1773233813326
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"cachedGrowthBookFeatures": {
|
||||
"tengu_claudeai_mcp_connectors": true,
|
||||
"tengu_event_sampling_config": {},
|
||||
"tengu_frond_boric": {},
|
||||
"tengu_log_segment_events": false,
|
||||
"tengu_log_datadog_events": true,
|
||||
"tengu_marble_anvil": true,
|
||||
"tengu_tool_pear": false,
|
||||
"tengu_scarf_coffee": false,
|
||||
"tengu_herring_clock": false,
|
||||
"tengu_keybinding_customization_release": true,
|
||||
"tengu_marble_whisper": true,
|
||||
"tengu_amber_quartz": false,
|
||||
"tengu_thinkback": false,
|
||||
"tengu_cicada_nap_ms": 0,
|
||||
"tengu_miraculo_the_bard": false,
|
||||
"tengu_miraculo_the_bard2": false,
|
||||
"tengu_paper_halyard": false,
|
||||
"tengu_chomp_inflection": false,
|
||||
"tengu_marble_sandcastle": true,
|
||||
"tengu_desktop_upsell": {
|
||||
"enable_shortcut_tip": false,
|
||||
"enable_startup_dialog": false
|
||||
},
|
||||
"tengu_marble_lantern_disabled": false,
|
||||
"tengu_pid_based_version_locking": true,
|
||||
"tengu_mcp_elicitation": false,
|
||||
"tengu_kairos_cron": true,
|
||||
"tengu_pebble_leaf_prune": false,
|
||||
"tengu_swinburne_dune": false,
|
||||
"tengu_coral_fern": false,
|
||||
"tengu_basalt_3kr": false,
|
||||
"tengu_summarize_tool_results": true,
|
||||
"tengu_bergotte_lantern": false,
|
||||
"tengu_sotto_voce": true,
|
||||
"tengu_system_prompt_global_cache": true,
|
||||
"tengu_turtle_carbon": true,
|
||||
"tengu_glacier_2xr": false,
|
||||
"enhanced_telemetry_beta": false,
|
||||
"tengu_streaming_tool_execution2": true,
|
||||
"tengu_moth_copse": false,
|
||||
"tengu_tool_search_unsupported_models": [
|
||||
"haiku"
|
||||
],
|
||||
"tengu_defer_all_bn4": false,
|
||||
"tengu_fgts": false,
|
||||
"tengu_tst_hint_m7r": false,
|
||||
"tengu_attribution_header": true,
|
||||
"tengu_prompt_cache_1h_config": {
|
||||
"allowlist": [
|
||||
"repl_main_thread*",
|
||||
"sdk",
|
||||
"auto_mode"
|
||||
]
|
||||
},
|
||||
"tengu_disable_streaming_to_non_streaming_fallback": false,
|
||||
"tengu_tool_input_aliasing": false,
|
||||
"tengu_satin_quoll": {}
|
||||
},
|
||||
"firstStartTime": "2026-03-11T12:56:06.706Z",
|
||||
"opusProMigrationComplete": true,
|
||||
"sonnet1m45MigrationComplete": true,
|
||||
"userID": "2525622ce171b408689c31f61f66ba3433629fa13b0656ed565073ba5f6dc2c6",
|
||||
"clientDataCache": {
|
||||
"data": {},
|
||||
"timestamp": 1773233813304
|
||||
},
|
||||
"changelogLastFetched": 1773233777137,
|
||||
"oauthAccount": {
|
||||
"accountUuid": "f093e810-c7e5-4d6b-902b-ec1fa73cbc94",
|
||||
"emailAddress": "eric.coissac@gmail.com",
|
||||
"organizationUuid": "c5e61747-337f-4fed-bf22-ca9925e92650",
|
||||
"hasExtraUsageEnabled": true,
|
||||
"billingType": "stripe_subscription",
|
||||
"accountCreatedAt": "2025-07-29T14:22:00.696404Z",
|
||||
"subscriptionCreatedAt": "2025-10-02T16:14:05.694173Z",
|
||||
"displayName": "Eric",
|
||||
"organizationRole": "admin",
|
||||
"workspaceRole": null,
|
||||
"organizationName": "eric.coissac@gmail.com's Organization"
|
||||
},
|
||||
"claudeCodeFirstTokenDate": "2025-10-05T14:58:34.301962Z",
|
||||
"penguinModeOrgEnabled": true,
|
||||
"groveConfigCache": {
|
||||
"f093e810-c7e5-4d6b-902b-ec1fa73cbc94": {
|
||||
"grove_enabled": true,
|
||||
"timestamp": 1773233813326
|
||||
}
|
||||
},
|
||||
"cachedExtraUsageDisabledReason": "out_of_credits"
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"cachedGrowthBookFeatures": {
|
||||
"tengu_claudeai_mcp_connectors": true,
|
||||
"tengu_event_sampling_config": {},
|
||||
"tengu_frond_boric": {},
|
||||
"tengu_log_segment_events": false,
|
||||
"tengu_log_datadog_events": true,
|
||||
"tengu_marble_anvil": true,
|
||||
"tengu_tool_pear": false,
|
||||
"tengu_scarf_coffee": false,
|
||||
"tengu_herring_clock": false,
|
||||
"tengu_keybinding_customization_release": true,
|
||||
"tengu_marble_whisper": true,
|
||||
"tengu_amber_quartz": false,
|
||||
"tengu_thinkback": false,
|
||||
"tengu_cicada_nap_ms": 0,
|
||||
"tengu_miraculo_the_bard": false,
|
||||
"tengu_miraculo_the_bard2": false,
|
||||
"tengu_paper_halyard": false,
|
||||
"tengu_chomp_inflection": false,
|
||||
"tengu_marble_sandcastle": true,
|
||||
"tengu_desktop_upsell": {
|
||||
"enable_shortcut_tip": false,
|
||||
"enable_startup_dialog": false
|
||||
},
|
||||
"tengu_marble_lantern_disabled": false,
|
||||
"tengu_pid_based_version_locking": true,
|
||||
"tengu_mcp_elicitation": false,
|
||||
"tengu_kairos_cron": true,
|
||||
"tengu_pebble_leaf_prune": false,
|
||||
"tengu_swinburne_dune": false,
|
||||
"tengu_coral_fern": false,
|
||||
"tengu_basalt_3kr": false,
|
||||
"tengu_summarize_tool_results": true,
|
||||
"tengu_bergotte_lantern": false,
|
||||
"tengu_sotto_voce": true,
|
||||
"tengu_system_prompt_global_cache": true,
|
||||
"tengu_turtle_carbon": true,
|
||||
"tengu_glacier_2xr": false,
|
||||
"enhanced_telemetry_beta": false,
|
||||
"tengu_streaming_tool_execution2": true,
|
||||
"tengu_moth_copse": false,
|
||||
"tengu_tool_search_unsupported_models": [
|
||||
"haiku"
|
||||
],
|
||||
"tengu_defer_all_bn4": false,
|
||||
"tengu_fgts": false,
|
||||
"tengu_tst_hint_m7r": false,
|
||||
"tengu_attribution_header": true,
|
||||
"tengu_prompt_cache_1h_config": {
|
||||
"allowlist": [
|
||||
"repl_main_thread*",
|
||||
"sdk",
|
||||
"auto_mode"
|
||||
]
|
||||
},
|
||||
"tengu_disable_streaming_to_non_streaming_fallback": false,
|
||||
"tengu_tool_input_aliasing": false,
|
||||
"tengu_satin_quoll": {},
|
||||
"tengu_amber_prism": false
|
||||
},
|
||||
"firstStartTime": "2026-03-11T12:56:06.706Z",
|
||||
"opusProMigrationComplete": true,
|
||||
"sonnet1m45MigrationComplete": true,
|
||||
"userID": "2525622ce171b408689c31f61f66ba3433629fa13b0656ed565073ba5f6dc2c6",
|
||||
"clientDataCache": {
|
||||
"data": {},
|
||||
"timestamp": 1773233813304
|
||||
},
|
||||
"changelogLastFetched": 1773233777137,
|
||||
"oauthAccount": {
|
||||
"accountUuid": "f093e810-c7e5-4d6b-902b-ec1fa73cbc94",
|
||||
"emailAddress": "eric.coissac@gmail.com",
|
||||
"organizationUuid": "c5e61747-337f-4fed-bf22-ca9925e92650",
|
||||
"hasExtraUsageEnabled": true,
|
||||
"billingType": "stripe_subscription",
|
||||
"accountCreatedAt": "2025-07-29T14:22:00.696404Z",
|
||||
"subscriptionCreatedAt": "2025-10-02T16:14:05.694173Z",
|
||||
"displayName": "Eric",
|
||||
"organizationRole": "admin",
|
||||
"workspaceRole": null,
|
||||
"organizationName": "eric.coissac@gmail.com's Organization"
|
||||
},
|
||||
"claudeCodeFirstTokenDate": "2025-10-05T14:58:34.301962Z",
|
||||
"penguinModeOrgEnabled": true,
|
||||
"groveConfigCache": {
|
||||
"f093e810-c7e5-4d6b-902b-ec1fa73cbc94": {
|
||||
"grove_enabled": true,
|
||||
"timestamp": 1773233813326
|
||||
}
|
||||
},
|
||||
"cachedExtraUsageDisabledReason": "out_of_credits"
|
||||
}
|
||||
2186
.claude-devcontainer/cache/changelog.md
vendored
Normal file
2186
.claude-devcontainer/cache/changelog.md
vendored
Normal file
File diff suppressed because it is too large
Load Diff
17
.claude-devcontainer/plugins/blocklist.json
Normal file
17
.claude-devcontainer/plugins/blocklist.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"fetchedAt": "2026-03-11T12:56:07.264Z",
|
||||
"plugins": [
|
||||
{
|
||||
"plugin": "code-review@claude-plugins-official",
|
||||
"added_at": "2026-02-11T03:16:31.424Z",
|
||||
"reason": "just-a-test",
|
||||
"text": "This is a test #5"
|
||||
},
|
||||
{
|
||||
"plugin": "fizz@testmkt-marketplace",
|
||||
"added_at": "2026-02-12T00:00:00.000Z",
|
||||
"reason": "security",
|
||||
"text": "this is a security test"
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,19 @@
|
||||
{"parentUuid":null,"isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","type":"user","message":{"role":"user","content":"Search for documentation about orla (github.com/dorcha-inc/orla) configuration, specifically:\n1. How to configure llm_backend for OpenAI-compatible API\n2. What config file format orla uses (YAML, TOML, JSON?)\n3. Where the config file should be placed (~/.orla, ~/.config/orla, orla.yaml, etc.)\n4. How to use a custom OpenAI-compatible endpoint with LM Studio\n\nLook at the source code at /usr/local/go/pkg/mod/github.com/dorcha-inc/ or any cached Go module. Also check if there are any orla config files in the system."},"uuid":"2f88d857-b27c-4a04-8199-33af4af15e10","timestamp":"2026-03-11T13:44:25.806Z"}
|
||||
{"parentUuid":"2f88d857-b27c-4a04-8199-33af4af15e10","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","message":{"model":"claude-haiku-4-5-20251001","id":"msg_01WRMXsZiGrk8P27RVrsVz5J","type":"message","role":"assistant","content":[{"type":"text","text":"I'll search for orla documentation and configuration information. Let me start by exploring the system for orla-related files and checking the Go modules."}],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":12529,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":12529,"ephemeral_1h_input_tokens":0},"output_tokens":5,"service_tier":"standard","inference_geo":"not_available"}},"requestId":"req_011CYwPjgdkNcUV5hmMaieH8","type":"assistant","uuid":"453a074b-95c7-40a7-92d9-75c1f60871b6","timestamp":"2026-03-11T13:44:27.428Z"}
|
||||
{"parentUuid":"453a074b-95c7-40a7-92d9-75c1f60871b6","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","message":{"model":"claude-haiku-4-5-20251001","id":"msg_01WRMXsZiGrk8P27RVrsVz5J","type":"message","role":"assistant","content":[{"type":"tool_use","id":"toolu_01MFu86Ver8CeFKTXEJ3oRxP","name":"Bash","input":{"command":"find /usr/local/go/pkg/mod/github.com/dorcha-inc -type f -name \"*.md\" -o -name \"*.go\" -o -name \"*.yaml\" -o -name \"*.yml\" -o -name \"*.toml\" -o -name \"*.json\" 2>/dev/null | head -30"},"caller":{"type":"direct"}}],"stop_reason":"tool_use","stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":12529,"cache_read_input_tokens":0,"output_tokens":162,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":12529},"inference_geo":"","iterations":[],"speed":"standard"}},"requestId":"req_011CYwPjgdkNcUV5hmMaieH8","type":"assistant","uuid":"cbb729b2-0cda-4dd6-be31-a70566af412d","timestamp":"2026-03-11T13:44:27.776Z"}
|
||||
{"parentUuid":"cbb729b2-0cda-4dd6-be31-a70566af412d","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","type":"progress","data":{"type":"hook_progress","hookEvent":"PostToolUse","hookName":"PostToolUse:Bash","command":"callback"},"parentToolUseID":"toolu_01MFu86Ver8CeFKTXEJ3oRxP","toolUseID":"toolu_01MFu86Ver8CeFKTXEJ3oRxP","timestamp":"2026-03-11T13:44:28.915Z","uuid":"7d01d136-c1d7-4bda-b83a-0dfbe3cdd8dd"}
|
||||
{"parentUuid":"cbb729b2-0cda-4dd6-be31-a70566af412d","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","type":"user","message":{"role":"user","content":[{"tool_use_id":"toolu_01MFu86Ver8CeFKTXEJ3oRxP","type":"tool_result","content":"/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/.githooks/README.md\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/.github/FUNDING.yml\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/.github/workflows/build.yml\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/.github/workflows/release.yml\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/.gitleaks.toml\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/.golangci.yml\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/.goreleaser.yaml\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/.vscode/extensions.json\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/.vscode/settings.json\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/CHANGELOG.md\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/CODE_OF_CONDUCT.md\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/CONTRIBUTING.md\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/CONTRIBUTORS.md\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/MAINTAINERS.md\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/README.md\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/SECURITY.md\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/cmd/orla-test/README.md\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/cmd/orla-test/call_cmd.go\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/cmd/orla-test/init_cmd.go\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/cmd/orla-test/main.go\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/cmd/orla-test/validate.go\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/cmd/orla/agent_cmd.go\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/cmd/orla/cache_cmd.go\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/cmd/orla/daemon_cmd.go\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/cmd/orla/main.go\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/cmd/orla/main_test.go\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/cmd/orla/serve_cmd.go\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/cmd/orla/tool_cmd.go\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/cmd/orla/tool_info_cmd.go\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/cmd/orla/tool_install_cmd.go","is_error":false}]},"uuid":"3595f29e-b29e-47b5-9038-fb279612d521","timestamp":"2026-03-11T13:44:28.915Z","sourceToolAssistantUUID":"cbb729b2-0cda-4dd6-be31-a70566af412d"}
|
||||
{"parentUuid":"3595f29e-b29e-47b5-9038-fb279612d521","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","message":{"model":"claude-haiku-4-5-20251001","id":"msg_01MCbhjbsfVEBevEHCJiDfTX","type":"message","role":"assistant","content":[{"type":"text","text":"Let me search for README and configuration files more specifically:"}],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":5,"cache_creation_input_tokens":1368,"cache_read_input_tokens":12529,"cache_creation":{"ephemeral_5m_input_tokens":1368,"ephemeral_1h_input_tokens":0},"output_tokens":3,"service_tier":"standard","inference_geo":"not_available"}},"requestId":"req_011CYwPjuSgNzwbFmNS5c1wn","type":"assistant","uuid":"2e05d35b-a758-4dad-8f40-18c7bd896100","timestamp":"2026-03-11T13:44:29.770Z"}
|
||||
{"parentUuid":"2e05d35b-a758-4dad-8f40-18c7bd896100","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","message":{"model":"claude-haiku-4-5-20251001","id":"msg_01MCbhjbsfVEBevEHCJiDfTX","type":"message","role":"assistant","content":[{"type":"tool_use","id":"toolu_014z1XCyo2WK9cACqxC5kMoE","name":"Read","input":{"file_path":"/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/README.md"},"caller":{"type":"direct"}}],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":5,"cache_creation_input_tokens":1368,"cache_read_input_tokens":12529,"cache_creation":{"ephemeral_5m_input_tokens":1368,"ephemeral_1h_input_tokens":0},"output_tokens":3,"service_tier":"standard","inference_geo":"not_available"}},"requestId":"req_011CYwPjuSgNzwbFmNS5c1wn","type":"assistant","uuid":"d655eebd-77b7-4463-b9bf-e94dd7f4d93a","timestamp":"2026-03-11T13:44:30.278Z"}
|
||||
{"parentUuid":"d655eebd-77b7-4463-b9bf-e94dd7f4d93a","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","type":"user","message":{"role":"user","content":[{"type":"tool_result","content":"Tool permission request failed: Error: Tool use aborted","is_error":true,"tool_use_id":"toolu_014z1XCyo2WK9cACqxC5kMoE"}]},"uuid":"71cbb790-8980-4dbe-874e-8b4278bc8761","timestamp":"2026-03-11T13:44:30.339Z","toolUseResult":"Error: Tool permission request failed: Error: Tool use aborted","sourceToolAssistantUUID":"d655eebd-77b7-4463-b9bf-e94dd7f4d93a"}
|
||||
{"parentUuid":"71cbb790-8980-4dbe-874e-8b4278bc8761","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","message":{"model":"claude-haiku-4-5-20251001","id":"msg_01MCbhjbsfVEBevEHCJiDfTX","type":"message","role":"assistant","content":[{"type":"tool_use","id":"toolu_01MkzKb5UxgTwtSWVYk1fY6A","name":"Bash","input":{"command":"find /usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1 -type f \\( -name \"*.md\" -o -name \"config*\" \\) | grep -i config"},"caller":{"type":"direct"}}],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":5,"cache_creation_input_tokens":1368,"cache_read_input_tokens":12529,"cache_creation":{"ephemeral_5m_input_tokens":1368,"ephemeral_1h_input_tokens":0},"output_tokens":3,"service_tier":"standard","inference_geo":"not_available"}},"requestId":"req_011CYwPjuSgNzwbFmNS5c1wn","type":"assistant","uuid":"95a62859-af65-409b-945f-afe0cc9859f9","timestamp":"2026-03-11T13:44:31.180Z"}
|
||||
{"parentUuid":"95a62859-af65-409b-945f-afe0cc9859f9","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","type":"user","message":{"role":"user","content":[{"type":"tool_result","content":"<tool_use_error>Cancelled: parallel tool call Read(/usr/local/go/pkg/mod/github.com/dorcha-…) errored</tool_use_error>","is_error":true,"tool_use_id":"toolu_01MkzKb5UxgTwtSWVYk1fY6A"}]},"uuid":"1cb9f541-7610-4371-8465-6a5e9f318ef4","timestamp":"2026-03-11T13:44:31.186Z","toolUseResult":"Cancelled: parallel tool call Read(/usr/local/go/pkg/mod/github.com/dorcha-…) errored","sourceToolAssistantUUID":"95a62859-af65-409b-945f-afe0cc9859f9"}
|
||||
{"parentUuid":"1cb9f541-7610-4371-8465-6a5e9f318ef4","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","message":{"model":"claude-haiku-4-5-20251001","id":"msg_01MCbhjbsfVEBevEHCJiDfTX","type":"message","role":"assistant","content":[{"type":"tool_use","id":"toolu_01E5HuDmbXkhQ76W7LmjsHoZ","name":"Bash","input":{"command":"find /usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1 -type f -name \"*.go\" | xargs grep -l \"llm_backend\\|config\" | head -10"},"caller":{"type":"direct"}}],"stop_reason":"tool_use","stop_sequence":null,"usage":{"input_tokens":5,"cache_creation_input_tokens":1368,"cache_read_input_tokens":12529,"output_tokens":281,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":1368},"inference_geo":"","iterations":[],"speed":"standard"}},"requestId":"req_011CYwPjuSgNzwbFmNS5c1wn","type":"assistant","uuid":"186d25b8-2bac-41d7-9c44-ae85f9532513","timestamp":"2026-03-11T13:44:31.842Z"}
|
||||
{"parentUuid":"186d25b8-2bac-41d7-9c44-ae85f9532513","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","type":"user","message":{"role":"user","content":[{"type":"tool_result","content":"<tool_use_error>Cancelled: parallel tool call Read(/usr/local/go/pkg/mod/github.com/dorcha-…) errored</tool_use_error>","is_error":true,"tool_use_id":"toolu_01E5HuDmbXkhQ76W7LmjsHoZ"}]},"uuid":"4101ff98-02cd-498f-bb79-d2036b317c8a","timestamp":"2026-03-11T13:44:31.848Z","toolUseResult":"Cancelled: parallel tool call Read(/usr/local/go/pkg/mod/github.com/dorcha-…) errored","sourceToolAssistantUUID":"186d25b8-2bac-41d7-9c44-ae85f9532513"}
|
||||
{"parentUuid":"4101ff98-02cd-498f-bb79-d2036b317c8a","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","message":{"model":"claude-haiku-4-5-20251001","id":"msg_01PAGPw45scRgRLysCoMGxr2","type":"message","role":"assistant","content":[{"type":"text","text":"Let me try a different approach:"}],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":6,"cache_creation_input_tokens":493,"cache_read_input_tokens":13897,"cache_creation":{"ephemeral_5m_input_tokens":493,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard","inference_geo":"not_available"}},"requestId":"req_011CYwPk7s3a5xGfh79ZPxqE","type":"assistant","uuid":"9ea694cd-a2a3-498c-a878-baa49c58000c","timestamp":"2026-03-11T13:44:32.688Z"}
|
||||
{"parentUuid":"9ea694cd-a2a3-498c-a878-baa49c58000c","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","message":{"model":"claude-haiku-4-5-20251001","id":"msg_01PAGPw45scRgRLysCoMGxr2","type":"message","role":"assistant","content":[{"type":"tool_use","id":"toolu_01XqVdyDYPWtWbH29c9Pmtcz","name":"Bash","input":{"command":"ls -la /usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/"},"caller":{"type":"direct"}}],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":6,"cache_creation_input_tokens":493,"cache_read_input_tokens":13897,"cache_creation":{"ephemeral_5m_input_tokens":493,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard","inference_geo":"not_available"}},"requestId":"req_011CYwPk7s3a5xGfh79ZPxqE","type":"assistant","uuid":"bbb0b718-7ea9-46f5-9740-7c1c6722381d","timestamp":"2026-03-11T13:44:33.023Z"}
|
||||
{"parentUuid":"bbb0b718-7ea9-46f5-9740-7c1c6722381d","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","message":{"model":"claude-haiku-4-5-20251001","id":"msg_01PAGPw45scRgRLysCoMGxr2","type":"message","role":"assistant","content":[{"type":"tool_use","id":"toolu_016nzp7WpZDqLwFYi4Z84Z3P","name":"Bash","input":{"command":"grep -r \"llm_backend\" /usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1 2>/dev/null | head -20"},"caller":{"type":"direct"}}],"stop_reason":"tool_use","stop_sequence":null,"usage":{"input_tokens":6,"cache_creation_input_tokens":493,"cache_read_input_tokens":13897,"output_tokens":174,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":493},"inference_geo":"","iterations":[],"speed":"standard"}},"requestId":"req_011CYwPk7s3a5xGfh79ZPxqE","type":"assistant","uuid":"ec4cdee6-b0aa-4e89-a458-d70299f1c358","timestamp":"2026-03-11T13:44:33.250Z"}
|
||||
{"parentUuid":"ec4cdee6-b0aa-4e89-a458-d70299f1c358","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","type":"progress","data":{"type":"hook_progress","hookEvent":"PostToolUse","hookName":"PostToolUse:Bash","command":"callback"},"parentToolUseID":"toolu_016nzp7WpZDqLwFYi4Z84Z3P","toolUseID":"toolu_016nzp7WpZDqLwFYi4Z84Z3P","timestamp":"2026-03-11T13:44:36.191Z","uuid":"ed1cd086-1858-42e6-a33c-6695935a9e29"}
|
||||
{"parentUuid":"ec4cdee6-b0aa-4e89-a458-d70299f1c358","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","type":"user","message":{"role":"user","content":[{"tool_use_id":"toolu_016nzp7WpZDqLwFYi4Z84Z3P","type":"tool_result","content":"/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/.github/workflows/release.yml: - name: Test with llm_backend configuration\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/.github/workflows/release.yml: - name: Test with llm_backend configuration\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/README.md:After installation, configure Orla to use your remote Ollama server by setting either the `OLLAMA_HOST` or the `ORLA_OLLAMA_HOST` environment variable, or using the `llm_backend` configuration in your `orla.yaml`:\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/README.md:llm_backend:\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/config/config.go:\tLLMBackend *core.LLMBackend `yaml:\"llm_backend,omitempty\" mapstructure:\"llm_backend\"` // LLM backend configuration (endpoint, type, api_key)\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/model/ollama.go:// 1. llm_backend.endpoint config (if llm_backend.type is \"ollama\")\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/model/ollama.go:\t// Check llm_backend config first\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/model/ollama.go:\t\t\treturn \"\", fmt.Errorf(\"llm_backend.endpoint is required if llm_backend is set\")\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/model/ollama.go:\t\t\treturn \"\", fmt.Errorf(\"llm_backend.type is required if llm_backend is set\")\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/model/ollama.go:\t\t\treturn \"\", fmt.Errorf(\"[BUG] llm_backend.type must be %s, got '%s': we should not be using this function for non-ollama inference servers\", core.LLMInferenceAPITypeOllama, cfg.LLMBackend.Type)\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/model/ollama_integration_test.go:// using llm_backend configuration. This test uses testcontainers to spin up an Ollama container\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/model/ollama_integration_test.go:\t// Test with llm_backend configuration pointing to the container\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/model/ollama_test.go:// Tests for getOllamaEndpoint with llm_backend configuration\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/model/ollama_test.go:\tassert.Contains(t, err.Error(), \"llm_backend.endpoint is required\")\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/model/ollama_test.go:\tassert.Contains(t, err.Error(), \"llm_backend.type is required\")\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/model/ollama_test.go:\tassert.Contains(t, err.Error(), \"llm_backend.type must be\")\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/model/openai.go:\t\treturn \"\", \"\", fmt.Errorf(\"llm_backend configuration is required for OpenAI-compatible API\")\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/model/openai.go:\t\treturn \"\", \"\", fmt.Errorf(\"llm_backend.endpoint is required\")\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/model/openai.go:\t\treturn \"\", \"\", fmt.Errorf(\"llm_backend.type is required if llm_backend is set\")\n/usr/local/go/pkg/mod/github.com/dorcha-inc/orla@v1.1.1/internal/model/openai.go:\t\treturn \"\", \"\", fmt.Errorf(\"[BUG] llm_backend.type must be %s, got '%s': we should not be using this function for non-openai inference servers\", core.LLMInferenceAPITypeOpenAI, cfg.LLMBackend.Type)","is_error":false}]},"uuid":"5992985f-2797-46aa-b0de-b01c601b9412","timestamp":"2026-03-11T13:44:36.191Z","sourceToolAssistantUUID":"ec4cdee6-b0aa-4e89-a458-d70299f1c358"}
|
||||
{"parentUuid":"bbb0b718-7ea9-46f5-9740-7c1c6722381d","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","type":"user","message":{"role":"user","content":[{"type":"tool_result","content":"The user doesn't want to proceed with this tool use. The tool use was rejected (eg. if it was a file edit, the new_string was NOT written to the file). STOP what you are doing and wait for the user to tell you how to proceed.","is_error":true,"tool_use_id":"toolu_01XqVdyDYPWtWbH29c9Pmtcz"}]},"uuid":"93dc9304-3433-4bb3-9677-0cacff2838d8","timestamp":"2026-03-11T13:48:40.019Z","toolUseResult":"User rejected tool use","sourceToolAssistantUUID":"bbb0b718-7ea9-46f5-9740-7c1c6722381d"}
|
||||
{"parentUuid":"93dc9304-3433-4bb3-9677-0cacff2838d8","isSidechain":true,"userType":"external","cwd":"/workspace","sessionId":"33cd9dcf-39f6-440b-a49f-a568379ee676","version":"2.1.71","gitBranch":"HEAD","agentId":"a5343c3e31ff952a3","slug":"rippling-frolicking-kettle","type":"user","message":{"role":"user","content":[{"type":"text","text":"[Request interrupted by user for tool use]"}]},"uuid":"9a098ad5-598c-4309-839f-6edd999922b8","timestamp":"2026-03-11T13:48:40.020Z"}
|
||||
@@ -0,0 +1 @@
|
||||
{"agentType":"Explore"}
|
||||
@@ -0,0 +1,74 @@
|
||||
# Snapshot file
|
||||
# Unset all aliases to avoid conflicts with functions
|
||||
unalias -a 2>/dev/null || true
|
||||
# Functions
|
||||
# Shell Options
|
||||
shopt -u autocd
|
||||
shopt -u assoc_expand_once
|
||||
shopt -u cdable_vars
|
||||
shopt -u cdspell
|
||||
shopt -u checkhash
|
||||
shopt -u checkjobs
|
||||
shopt -s checkwinsize
|
||||
shopt -s cmdhist
|
||||
shopt -u compat31
|
||||
shopt -u compat32
|
||||
shopt -u compat40
|
||||
shopt -u compat41
|
||||
shopt -u compat42
|
||||
shopt -u compat43
|
||||
shopt -u compat44
|
||||
shopt -s complete_fullquote
|
||||
shopt -u direxpand
|
||||
shopt -u dirspell
|
||||
shopt -u dotglob
|
||||
shopt -u execfail
|
||||
shopt -u expand_aliases
|
||||
shopt -u extdebug
|
||||
shopt -u extglob
|
||||
shopt -s extquote
|
||||
shopt -u failglob
|
||||
shopt -s force_fignore
|
||||
shopt -s globasciiranges
|
||||
shopt -s globskipdots
|
||||
shopt -u globstar
|
||||
shopt -u gnu_errfmt
|
||||
shopt -u histappend
|
||||
shopt -u histreedit
|
||||
shopt -u histverify
|
||||
shopt -s hostcomplete
|
||||
shopt -u huponexit
|
||||
shopt -u inherit_errexit
|
||||
shopt -s interactive_comments
|
||||
shopt -u lastpipe
|
||||
shopt -u lithist
|
||||
shopt -u localvar_inherit
|
||||
shopt -u localvar_unset
|
||||
shopt -s login_shell
|
||||
shopt -u mailwarn
|
||||
shopt -u no_empty_cmd_completion
|
||||
shopt -u nocaseglob
|
||||
shopt -u nocasematch
|
||||
shopt -u noexpand_translation
|
||||
shopt -u nullglob
|
||||
shopt -s patsub_replacement
|
||||
shopt -s progcomp
|
||||
shopt -u progcomp_alias
|
||||
shopt -s promptvars
|
||||
shopt -u restricted_shell
|
||||
shopt -u shift_verbose
|
||||
shopt -s sourcepath
|
||||
shopt -u varredir_close
|
||||
shopt -u xpg_echo
|
||||
set -o braceexpand
|
||||
set -o hashall
|
||||
set -o interactive-comments
|
||||
set -o monitor
|
||||
set -o onecmd
|
||||
shopt -s expand_aliases
|
||||
# Aliases
|
||||
# Check for rg availability
|
||||
if ! (unalias rg 2>/dev/null; command -v rg) >/dev/null 2>&1; then
|
||||
alias rg='/home/devuser/.local/share/zed/external_agents/claude-agent-acp/0.21.0/node_modules/\@anthropic-ai/claude-agent-sdk/vendor/ripgrep/arm64-linux/rg'
|
||||
fi
|
||||
export PATH=/usr/local/cargo/bin\:/usr/local/go/bin\:/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
|
||||
@@ -8,4 +8,6 @@
|
||||
"terminal.integrated.shell.linux": "/bin/bash",
|
||||
},
|
||||
"features": {},
|
||||
"postCreateCommand": "npm install -g @anthropic-ai/claude-code",
|
||||
"shutdownAction": "stopCompose",
|
||||
}
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
services:
|
||||
pmocrazy-coder:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: Dockerfile
|
||||
image: niepce.petite-maison-orange.fr/public/pmocrazycoder:latest
|
||||
volumes:
|
||||
- ..:/workspace
|
||||
- ./config/claude:/home/devuser/.claude
|
||||
- ./config/opencode:/home/devuser/.config/opencode
|
||||
- ./config/aichat:/home/devuser/.config/aichat
|
||||
- ./config/ai_index:/workspace/.ai_index
|
||||
- ./config/cargo-registry:/home/devuser/.cargo/registry
|
||||
- ./config/cargo-git:/home/devuser/.cargo/git
|
||||
- ./config/cargo-bin:/home/devuser/.cargo/bin
|
||||
- ./config/go-cache:/home/devuser/.cache/go
|
||||
- ./config/go-bin:/home/devuser/go/bin
|
||||
- ./config/python-local:/home/devuser/.local
|
||||
- ./config/npm-cache:/home/devuser/.npm
|
||||
- ./config/r-libs:/home/devuser/R
|
||||
working_dir: /workspace
|
||||
ports:
|
||||
- "1249:1248"
|
||||
environment:
|
||||
- LOCAL_LLM_API=http://host.docker.internal:1248/v1
|
||||
- CLAUDE_CONFIG_DIR=/home/devuser/.claude
|
||||
user: devuser
|
||||
entrypoint: ["/usr/local/bin/entrypoint.sh"]
|
||||
command: ["bash", "-c", "tail -f /dev/null"]
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -209,5 +209,5 @@ cython_debug/
|
||||
# PyPI configuration file
|
||||
.pypirc
|
||||
|
||||
# AI Index
|
||||
.ai_index/
|
||||
.devcontainer/config/
|
||||
pmocrazycoder-latest.oci.tar
|
||||
|
||||
25
Dockerfile
25
Dockerfile
@@ -24,13 +24,12 @@ RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable && \
|
||||
|
||||
RUN npm install -g typescript tsc @types/node eslint prettier pyright typescript-language-server
|
||||
|
||||
RUN cargo binstall --strategies crate-meta-data jj-cli
|
||||
|
||||
RUN cargo install --git https://github.com/nilskch/jj-lsp.git
|
||||
RUN cargo binstall --strategies crate-meta-data jj-cli aichat \
|
||||
&& cargo install --git https://github.com/nilskch/jj-lsp.git
|
||||
|
||||
RUN gem install github-linguist
|
||||
|
||||
RUN pip install --no-cache-dir --break-system-packages ruff fastmcp ipython
|
||||
RUN pip install --no-cache-dir --break-system-packages ruff fastmcp ipython tasklin
|
||||
|
||||
RUN curl -fsSL https://opencode.ai/install | bash && \
|
||||
mkdir -p /root/.config/opencode && \
|
||||
@@ -39,11 +38,11 @@ RUN curl -fsSL https://opencode.ai/install | bash && \
|
||||
ENV GOPATH=/usr/local/go
|
||||
ENV GOBIN=/usr/local/go/bin
|
||||
RUN go install golang.org/x/tools/gopls@latest \
|
||||
&& go install github.com/isaacphi/mcp-language-server@latest \
|
||||
&& go install github.com/dorcha-inc/orla/cmd/orla@latest
|
||||
&& go install github.com/isaacphi/mcp-language-server@latest
|
||||
|
||||
RUN mkdir -p /etc/bash_completion.d \
|
||||
&& orla completion bash > /etc/bash_completion.d/orla \
|
||||
&& curl https://raw.githubusercontent.com/sigoden/aichat/main/scripts/completions/aichat.bash \
|
||||
> /etc/bash_completion.d/aichat \
|
||||
&& jj util completion bash > /etc/bash_completion.d/jj
|
||||
|
||||
RUN rustup component add rust-analyzer --toolchain nightly
|
||||
@@ -71,6 +70,18 @@ COPY --chown=${USERNAME}:${USERNAME} opencode /home/${USERNAME}/.config/opencode
|
||||
USER $USERNAME
|
||||
WORKDIR /workspace
|
||||
|
||||
ARG OCI_VERSION=latest
|
||||
ARG OCI_CREATED=unknown
|
||||
ARG OCI_REVISION=unknown
|
||||
|
||||
LABEL org.opencontainers.image.title="PMOCrazyCoder" \
|
||||
org.opencontainers.image.description="AI-powered dev container with Rust, Go, Python, Node, Jujutsu, Claude Code and opencode" \
|
||||
org.opencontainers.image.url="https://niepce.petite-maison-orange.fr/public/pmocrazycoder" \
|
||||
org.opencontainers.image.source="https://niepce.petite-maison-orange.fr/public/pmocrazycoder" \
|
||||
org.opencontainers.image.version="${OCI_VERSION}" \
|
||||
org.opencontainers.image.created="${OCI_CREATED}" \
|
||||
org.opencontainers.image.revision="${OCI_REVISION}" \
|
||||
org.opencontainers.image.licenses="CECILL-2.1"
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||
CMD ["/bin/bash"]
|
||||
|
||||
153
Makefile
153
Makefile
@@ -1,28 +1,120 @@
|
||||
# Makefile pour dev container AI + MCP bootstrap
|
||||
# =============================================================================
|
||||
# Image identity
|
||||
# =============================================================================
|
||||
|
||||
IMAGE_NAME := pmocrazycoder
|
||||
IMAGE_TAG := latest
|
||||
|
||||
# =============================================================================
|
||||
# Registry
|
||||
# =============================================================================
|
||||
|
||||
REGISTRY := niepce.petite-maison-orange.fr/public
|
||||
|
||||
# =============================================================================
|
||||
# Build platforms
|
||||
# =============================================================================
|
||||
|
||||
PLATFORMS := linux/amd64,linux/arm64
|
||||
|
||||
# =============================================================================
|
||||
# Derived image identifiers
|
||||
# =============================================================================
|
||||
|
||||
FULL_IMAGE := $(REGISTRY)/$(IMAGE_NAME):$(IMAGE_TAG)
|
||||
OCI_ARCHIVE := $(IMAGE_NAME)-$(IMAGE_TAG).oci.tar
|
||||
|
||||
# =============================================================================
|
||||
# Docker buildx builder
|
||||
# =============================================================================
|
||||
|
||||
BUILDER := $(IMAGE_NAME)-builder
|
||||
|
||||
# =============================================================================
|
||||
# OCI image annotations (injected via --build-arg)
|
||||
# =============================================================================
|
||||
|
||||
OCI_VERSION := $(IMAGE_TAG)
|
||||
OCI_CREATED := $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
OCI_REVISION := $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
|
||||
|
||||
# =============================================================================
|
||||
# Build context
|
||||
# =============================================================================
|
||||
|
||||
# Variables
|
||||
PROJECT_DIR := $(shell pwd)
|
||||
CONTAINER_NAME := ai-dev-container
|
||||
BUILD_CONTEXT := .
|
||||
DOCKERFILE := Dockerfile
|
||||
|
||||
BUILD_ARGS := \
|
||||
--build-arg OCI_VERSION=$(OCI_VERSION) \
|
||||
--build-arg OCI_CREATED=$(OCI_CREATED) \
|
||||
--build-arg OCI_REVISION=$(OCI_REVISION)
|
||||
|
||||
# =============================================================================
|
||||
# Dev container
|
||||
# =============================================================================
|
||||
|
||||
WORKSPACE := /workspace
|
||||
CONTAINER_NAME := ai-dev-container
|
||||
MCP_LOG := $(WORKSPACE)/.ai_index/mcp.log
|
||||
|
||||
# --- Dev Container Management ---
|
||||
# =============================================================================
|
||||
# Targets
|
||||
# =============================================================================
|
||||
|
||||
# Build the container
|
||||
.PHONY: all build build-multiplatform push run run-mcp \
|
||||
init-index mcp-list embeddings update-graph \
|
||||
restart-mcp bootstrap clean clean-builder help
|
||||
|
||||
## all : Build multi-platform image, push to registry
|
||||
all: build-multiplatform push
|
||||
|
||||
## build : Build for the native platform and load into the local Docker daemon
|
||||
build:
|
||||
docker build -t $(CONTAINER_NAME) .
|
||||
docker build $(BUILD_ARGS) \
|
||||
--tag $(FULL_IMAGE) \
|
||||
--file $(DOCKERFILE) \
|
||||
$(BUILD_CONTEXT)
|
||||
|
||||
# Run interactive container with mounted project
|
||||
## build-multiplatform : Build for $(PLATFORMS) and export as a local OCI archive
|
||||
build-multiplatform: .builder-ready
|
||||
docker buildx build $(BUILD_ARGS) \
|
||||
--builder $(BUILDER) \
|
||||
--platform $(PLATFORMS) \
|
||||
--tag $(FULL_IMAGE) \
|
||||
--file $(DOCKERFILE) \
|
||||
--provenance=false \
|
||||
--output type=oci,dest=$(OCI_ARCHIVE) \
|
||||
$(BUILD_CONTEXT)
|
||||
|
||||
# Create the buildx builder with docker-container driver (once)
|
||||
.builder-ready:
|
||||
docker buildx inspect $(BUILDER) > /dev/null 2>&1 \
|
||||
|| docker buildx create --name $(BUILDER) --driver docker-container --bootstrap
|
||||
touch .builder-ready
|
||||
|
||||
## push : Push the OCI archive to the registry using skopeo
|
||||
push: $(OCI_ARCHIVE)
|
||||
skopeo copy \
|
||||
--dest-tls-verify=true \
|
||||
--multi-arch all \
|
||||
oci-archive:$(OCI_ARCHIVE) \
|
||||
docker://$(FULL_IMAGE)
|
||||
|
||||
# Ensure the OCI archive exists before pushing
|
||||
$(OCI_ARCHIVE):
|
||||
$(MAKE) build-multiplatform
|
||||
|
||||
## run : Run interactive container with mounted project
|
||||
run:
|
||||
docker run -v $(PROJECT_DIR):$(WORKSPACE) -it --rm $(CONTAINER_NAME)
|
||||
docker run -v $(PROJECT_DIR):$(WORKSPACE) -it --rm $(FULL_IMAGE)
|
||||
|
||||
# Run container with MCP server in background
|
||||
## run-mcp : Run container with MCP server in background
|
||||
run-mcp:
|
||||
docker run -v $(PROJECT_DIR):$(WORKSPACE) -it --rm $(CONTAINER_NAME) bash
|
||||
docker run -v $(PROJECT_DIR):$(WORKSPACE) -it --rm $(FULL_IMAGE) bash
|
||||
|
||||
# --- MCP / Index Management ---
|
||||
|
||||
# Initialize .ai_index
|
||||
## init-index : Initialize .ai_index directory structure
|
||||
init-index:
|
||||
@echo "[MAKE] Initializing .ai_index..."
|
||||
mkdir -p $(PROJECT_DIR)/.ai_index/ast
|
||||
@@ -31,36 +123,45 @@ init-index:
|
||||
sqlite3 $(PROJECT_DIR)/.ai_index/graph.db "VACUUM;"; \
|
||||
fi
|
||||
|
||||
# Run MCP tool (list imports)
|
||||
## mcp-list : Run MCP list_imports tool
|
||||
mcp-list:
|
||||
@echo "[MAKE] Running MCP list_imports.py..."
|
||||
python3 $(PROJECT_DIR)/opt/dev-tools/list_imports.py --project $(WORKSPACE)
|
||||
|
||||
# Update embeddings (example)
|
||||
## embeddings : Generate embeddings
|
||||
embeddings:
|
||||
@echo "[MAKE] Generating embeddings..."
|
||||
python3 $(PROJECT_DIR)/opt/dev-tools/generate_embeddings.py --project $(WORKSPACE)
|
||||
|
||||
# Update graph (example)
|
||||
## update-graph : Update dependency graph
|
||||
update-graph:
|
||||
@echo "[MAKE] Updating dependency graph..."
|
||||
python3 $(PROJECT_DIR)/opt/dev-tools/update_graph.py --project $(WORKSPACE)
|
||||
|
||||
# Clean logs and temporary files
|
||||
clean:
|
||||
@echo "[MAKE] Cleaning .ai_index..."
|
||||
rm -f $(PROJECT_DIR)/.ai_index/*.log
|
||||
rm -rf $(PROJECT_DIR)/.ai_index/ast/*
|
||||
rm -rf $(PROJECT_DIR)/.ai_index/embeddings/*
|
||||
|
||||
# Restart MCP server inside container
|
||||
## restart-mcp : Restart MCP server inside running container
|
||||
restart-mcp:
|
||||
docker exec -it $(CONTAINER_NAME) bash -c "\
|
||||
pkill -f mcp-server; \
|
||||
/opt/bin/mcp-server --project $(WORKSPACE) > $(MCP_LOG) 2>&1 & \
|
||||
"
|
||||
|
||||
# --- Bootstrap for new project ---
|
||||
# Build container, init index
|
||||
## bootstrap : Build container and init index
|
||||
bootstrap: build init-index
|
||||
@echo "[MAKE] Bootstrap complete. Run 'make run' to start the container."
|
||||
|
||||
## clean : Remove OCI archive, local image and generated files
|
||||
clean: clean-builder
|
||||
docker rmi --force $(FULL_IMAGE) 2>/dev/null || true
|
||||
rm -f $(OCI_ARCHIVE)
|
||||
rm -f $(PROJECT_DIR)/.ai_index/*.log
|
||||
rm -rf $(PROJECT_DIR)/.ai_index/ast/*
|
||||
rm -rf $(PROJECT_DIR)/.ai_index/embeddings/*
|
||||
|
||||
## clean-builder : Remove the buildx builder
|
||||
clean-builder:
|
||||
docker buildx rm $(BUILDER) 2>/dev/null || true
|
||||
rm -f .builder-ready
|
||||
|
||||
## help : Show this help
|
||||
help:
|
||||
@grep -E '^## ' $(MAKEFILE_LIST) | sed 's/^## //'
|
||||
|
||||
140
README.md
140
README.md
@@ -1,19 +1,133 @@
|
||||
# 🧠 PMOCrazyCoder
|
||||
# PMOCrazyCoder
|
||||
|
||||
Un assistant IA **local**, pour coder en Go, Rust et R —
|
||||
sans cloud, sans API key, tout sur votre M3 Max.
|
||||
Environnement de développement conteneurisé avec assistance IA intégrée — Go, Rust, Python, TypeScript, R, Ruby — et outillage IA local (LM Studio) ou cloud (Claude Pro).
|
||||
|
||||
## 🎯 Vision
|
||||
## Vision
|
||||
|
||||
> *Un indexeur de code, des graphes de dépendances, et un assistant intelligent —
|
||||
> intégré à Zed, 100 % local.*
|
||||
> Un container de développement complet, multi-langages, avec LSP, outils IA et MCP intégrés,
|
||||
> utilisable depuis Zed, VS Code ou Cursor, avec persistance par projet.
|
||||
|
||||
### 🛠️ Ce qu’on construit
|
||||
## Ce que contient l'image
|
||||
|
||||
- ✅ MCP tools pour Zed (ex : `get_similar_functions`, `explain_imports`)
|
||||
- ✅ Indexeur de code (Go / Rust / R) via Tree-sitter
|
||||
- ✅ Graphe de dépendances & similarité (stocké localement)
|
||||
- ✅ Tout tourne en local : **LM Studio** (`localhost:1248`) + LanceDB + Rust/Python
|
||||
*(hors conteneur — le conteneur y accède via `host.docker.internal:1248`)*
|
||||
### Langages et compilateurs
|
||||
- **Go** (dernière version stable via script)
|
||||
- **Rust** (stable + nightly, avec rustfmt, clippy, rust-analyzer, rust-src)
|
||||
- **Python 3** (avec ruff, fastmcp, ipython, tasklin)
|
||||
- **Node.js / npm** (avec TypeScript, ESLint, Prettier, Pyright, typescript-language-server)
|
||||
- **Ruby** (avec github-linguist)
|
||||
- **R**
|
||||
- **Clang / LLVM** (clangd inclus)
|
||||
|
||||
### 📦 Structure future (à venir)
|
||||
### Outils de développement
|
||||
- `jj` (Jujutsu VCS) + `jj-lsp`
|
||||
- `gopls`, `mcp-language-server`
|
||||
- `cargo-edit`, `cargo-watch`, `cargo-outdated`, `cargo-make`, `cargo-binstall`
|
||||
- `sqlite3`, `cmake`, `make`, `git`
|
||||
- `aichat` (client LLM CLI)
|
||||
|
||||
### Assistants IA
|
||||
- **Claude Code** (installé au `postCreateCommand`)
|
||||
- **opencode** (configuré via l'entrypoint)
|
||||
- **aichat** (configuré via l'entrypoint, connecté au LLM local)
|
||||
|
||||
## Utilisation rapide
|
||||
|
||||
### Ajouter l'environnement à un projet existant
|
||||
|
||||
```bash
|
||||
curl -fsSL https://gargoton.petite-maison-orange.fr/eric/PMOCrazycoder/raw/branch/main/setup-devcontainer.sh | bash
|
||||
```
|
||||
|
||||
Ou avec un endpoint LLM personnalisé :
|
||||
|
||||
```bash
|
||||
LOCAL_LLM_API=http://monserveur:1248/v1 bash setup-devcontainer.sh
|
||||
```
|
||||
|
||||
Le script télécharge les fichiers `devcontainer.json` et `docker-compose.yml` directement depuis le dépôt Gitea, crée les répertoires de persistance dans `.devcontainer/config/` et met à jour `.gitignore`.
|
||||
|
||||
### Ouvrir dans le container
|
||||
|
||||
Ouvrir le projet dans VS Code, Zed ou Cursor et choisir "Reopen in Container". L'image est tirée automatiquement depuis le registry.
|
||||
|
||||
### Authentifier Claude Code
|
||||
|
||||
Dans le panneau Claude Agent de Zed, lancer `/login` et choisir "Log in with Claude.ai" (abonnement Pro/Max).
|
||||
|
||||
## Persistance par projet
|
||||
|
||||
Toutes les données et caches sont persistés dans `.devcontainer/config/` (ignoré par git) :
|
||||
|
||||
| Répertoire | Contenu |
|
||||
|---|---|
|
||||
| `config/claude/` | Sessions et config Claude Code |
|
||||
| `config/opencode/` | Config opencode |
|
||||
| `config/aichat/` | Config aichat |
|
||||
| `config/ai_index/` | Index de code du projet |
|
||||
| `config/cargo-registry/` | Cache crates.io |
|
||||
| `config/cargo-git/` | Cache dépendances git Cargo |
|
||||
| `config/cargo-bin/` | Binaires Rust installés pour le projet |
|
||||
| `config/go-cache/` | Cache modules Go |
|
||||
| `config/go-bin/` | Binaires Go installés pour le projet |
|
||||
| `config/python-local/` | Paquets pip user + gems Ruby |
|
||||
| `config/npm-cache/` | Cache npm |
|
||||
| `config/r-libs/` | Paquets R installés |
|
||||
|
||||
### Installer des binaires persistants
|
||||
|
||||
```bash
|
||||
# Rust — persiste dans .devcontainer/config/cargo-bin/
|
||||
cargo install cargo-nextest
|
||||
|
||||
# Go — persiste dans .devcontainer/config/go-bin/
|
||||
GOBIN=~/go/bin go install github.com/some/tool@latest
|
||||
|
||||
# Python — persiste dans .devcontainer/config/python-local/
|
||||
pip install --user monpaquet
|
||||
|
||||
# R — persiste dans .devcontainer/config/r-libs/
|
||||
R -e 'install.packages("tidyverse")'
|
||||
```
|
||||
|
||||
## LLM local
|
||||
|
||||
L'entrypoint configure automatiquement opencode et aichat pour pointer sur `LOCAL_LLM_API`
|
||||
(défaut : `http://host.docker.internal:1248/v1`).
|
||||
|
||||
Variables d'environnement disponibles dans le container :
|
||||
|
||||
| Variable | Défaut | Description |
|
||||
|---|---|---|
|
||||
| `LOCAL_LLM_API` | `http://host.docker.internal:1248/v1` | Endpoint OpenAI-compatible |
|
||||
| `LLM_MODEL` | `ollama:qwen/qwen3-coder-next@4bit` | Modèle à utiliser |
|
||||
| `TEMPERATURE` | `0.5` | Température |
|
||||
| `NUM_CTX` | `32768` | Taille de contexte |
|
||||
| `MAXTOKEN` | `4096` | Tokens max en sortie |
|
||||
|
||||
## Construire et publier l'image
|
||||
|
||||
```bash
|
||||
# Build natif (local)
|
||||
make build
|
||||
|
||||
# Build multi-arch (amd64 + arm64) + push vers le registry
|
||||
make all
|
||||
|
||||
# Push uniquement (si l'archive OCI existe déjà)
|
||||
make push
|
||||
|
||||
# Lister toutes les targets
|
||||
make help
|
||||
```
|
||||
|
||||
L'image est publiée sur `niepce.petite-maison-orange.fr/public/pmocrazycoder:latest`.
|
||||
Le push utilise `skopeo` — assurez-vous d'être authentifié sur le registry.
|
||||
|
||||
## Sources
|
||||
|
||||
- Dépôt git : `https://gargoton.petite-maison-orange.fr/eric/PMOCrazycoder`
|
||||
- Registry OCI : `niepce.petite-maison-orange.fr/public/pmocrazycoder:latest`
|
||||
|
||||
## Licence
|
||||
|
||||
CECILL-2.1
|
||||
|
||||
@@ -1,16 +1,48 @@
|
||||
#!/bin/bash
|
||||
|
||||
LOCAL_LLM_API=${LOCAL_LLM_API:-http://host.docker.internal:1248/v1}
|
||||
MODEL="${LLM_MODEL:-qwen3-coder}"
|
||||
|
||||
DIFF=$(jj diff)
|
||||
PROMPT='Analyse ce diff et réponds UNIQUEMENT avec un objet JSON valide contenant "title" (string) et "message" (string) pour le message de commit. Pas de texte avant ou après le JSON.'
|
||||
|
||||
CONTENT="${PROMPT}
|
||||
${DIFF}"
|
||||
|
||||
REQUEST=$(jq -n --arg content "$CONTENT" '{"model": "qwen3-coder", "messages": [{"role": "user", "content": $content}]}')
|
||||
|
||||
curl -s -X POST \
|
||||
llm_query() {
|
||||
local content="$1"
|
||||
jq -n --arg content "$content" --arg model "$MODEL" \
|
||||
'{"model": $model, "messages": [{"role": "user", "content": $content}]}' \
|
||||
| curl -s -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$REQUEST" \
|
||||
"$LOCAL_LLM_API/chat/completions" | jq -r '.choices[0].message.content' | jq -r '.title + "\n\n" + .message'
|
||||
-d @- \
|
||||
"$LOCAL_LLM_API/chat/completions" \
|
||||
| jq -r '.choices[0].message.content'
|
||||
}
|
||||
|
||||
# Get list of modified files
|
||||
FILES=$(jj diff --summary | awk '{print $2}')
|
||||
|
||||
if [[ -z "$FILES" ]]; then
|
||||
echo "No changes to commit." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Pass 1: summarize each file diff individually
|
||||
SUMMARIES=""
|
||||
while IFS= read -r file; do
|
||||
FILE_DIFF=$(jj diff "$file" 2>/dev/null)
|
||||
if [[ -z "$FILE_DIFF" ]]; then
|
||||
continue
|
||||
fi
|
||||
PROMPT="Résume en 2-3 phrases les changements apportés dans ce diff pour le fichier '$file'. Sois concis et factuel.
|
||||
|
||||
$FILE_DIFF"
|
||||
SUMMARY=$(llm_query "$PROMPT")
|
||||
SUMMARIES="${SUMMARIES}### $file
|
||||
$SUMMARY
|
||||
|
||||
"
|
||||
done <<< "$FILES"
|
||||
|
||||
# Pass 2: generate commit message from summaries
|
||||
COMMIT_PROMPT="À partir des résumés suivants de fichiers modifiés, génère un message de commit git.
|
||||
Réponds UNIQUEMENT avec un objet JSON valide contenant \"title\" (string, max 72 chars, en anglais, style imperative) et \"message\" (string, détails en français). Pas de texte avant ou après le JSON.
|
||||
|
||||
$SUMMARIES"
|
||||
|
||||
llm_query "$COMMIT_PROMPT" | jq -r '.title + "\n\n" + .message'
|
||||
|
||||
@@ -6,7 +6,7 @@ export USERNAME=${USERNAME:-devuser}
|
||||
export WORKSPACE=${WORKSPACE:-/workspace}
|
||||
export LOCAL_LLM_API=${LOCAL_LLM_API:-http://host.docker.internal:1248/v1}
|
||||
export LLM_MODEL=${LLM_MODEL:-'ollama:qwen/qwen3-coder-next@4bit'}
|
||||
export ORLA_OLLAMA_HOST=$(sed -E 's@(https?://[^/]+).*$@\1@' <<< $LOCAL_LLM_API)
|
||||
export AICHAT_API_BASE=$(sed -E 's@(https?://[^/]+).*$@\1@' <<< $LOCAL_LLM_API)
|
||||
export MAXTOKEN=${MAXTOKEN:-4096}
|
||||
export NUM_CTX=${NUM_CTX:-32768}
|
||||
export REPEAT_PENALTY=${REPEAT_PENALTY:-1.3}
|
||||
@@ -26,10 +26,28 @@ fi
|
||||
if [ -n "$LOCAL_LLM_API" ]; then
|
||||
if ! grep -q "LOCAL_LLM_API" /home/${USERNAME}/.bashrc; then
|
||||
echo "export LOCAL_LLM_API=$LOCAL_LLM_API" >> /home/${USERNAME}/.bashrc
|
||||
echo "export ORLA_OLLAMA_HOST=$ORLA_OLLAMA_HOST" >> /home/${USERNAME}/.bashrc
|
||||
echo "export ORLA_MODEL='${LLM_MODEL}'" >> /home/${USERNAME}/.bashrc
|
||||
echo "export AICHAT_API_BASE=$AICHAT_API_BASE" >> /home/${USERNAME}/.bashrc
|
||||
echo "export PATH=\$HOME/.cargo/bin:\$HOME/go/bin:\$HOME/.local/bin:\$PATH" >> /home/${USERNAME}/.bashrc
|
||||
fi
|
||||
|
||||
# --- Configure aichat ---
|
||||
mkdir -p /home/${USERNAME}/.config/aichat
|
||||
AICHAT_CONFIG=/home/${USERNAME}/.config/aichat/config.yaml
|
||||
cat > $AICHAT_CONFIG <<EOF
|
||||
model: lmstudio:${LLM_MODEL#*:}
|
||||
clients:
|
||||
- type: openai-compatible
|
||||
name: lmstudio
|
||||
api_base: ${LOCAL_LLM_API}
|
||||
api_key: placeholder
|
||||
models:
|
||||
- name: ${LLM_MODEL#*:}
|
||||
max_input_tokens: ${NUM_CTX}
|
||||
temperature: ${TEMPERATURE}
|
||||
top_p: ${TOP_P}
|
||||
EOF
|
||||
chown ${USERNAME}:${USERNAME} ${AICHAT_CONFIG}
|
||||
|
||||
mkdir -p /home/${USERNAME}/.config/opencode
|
||||
CONFIG_FILE=/home/${USERNAME}/.config/opencode/opencode.json
|
||||
|
||||
|
||||
99
setup-devcontainer.sh
Executable file
99
setup-devcontainer.sh
Executable file
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env bash
|
||||
# setup-devcontainer.sh
|
||||
#
|
||||
# Adds the PMOCrazyCoder devcontainer environment to any project.
|
||||
# Usage: bash setup-devcontainer.sh [project-dir]
|
||||
#
|
||||
# Example (run from the project root):
|
||||
# bash setup-devcontainer.sh
|
||||
#
|
||||
# Or download and run directly:
|
||||
# curl -fsSL https://gargoton.petite-maison-orange.fr/eric/PMOCrazycoder/raw/branch/main/setup-devcontainer.sh | bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT_DIR="${1:-$(pwd)}"
|
||||
DEVCONTAINER_DIR="$PROJECT_DIR/.devcontainer"
|
||||
LOCAL_LLM_API="${LOCAL_LLM_API:-http://host.docker.internal:1248/v1}"
|
||||
|
||||
GIT_RAW="https://gargoton.petite-maison-orange.fr/eric/PMOCrazycoder/raw/branch/main"
|
||||
|
||||
# --- Colors ---
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RESET='\033[0m'
|
||||
info() { echo -e "${GREEN}[setup]${RESET} $*"; }
|
||||
warning() { echo -e "${YELLOW}[setup]${RESET} $*"; }
|
||||
error() { echo -e "${RED}[setup]${RESET} $*" >&2; exit 1; }
|
||||
|
||||
fetch() {
|
||||
local src="$1" dst="$2"
|
||||
curl -fsSL "$GIT_RAW/$src" -o "$dst" \
|
||||
|| error "Failed to fetch $src from $GIT_RAW"
|
||||
}
|
||||
|
||||
# --- Checks ---
|
||||
[[ -d "$PROJECT_DIR" ]] || error "Directory not found: $PROJECT_DIR"
|
||||
command -v curl >/dev/null || error "curl is required"
|
||||
|
||||
# --- .devcontainer/ ---
|
||||
info "Creating .devcontainer structure in $PROJECT_DIR"
|
||||
mkdir -p "$DEVCONTAINER_DIR/config/claude"
|
||||
mkdir -p "$DEVCONTAINER_DIR/config/opencode"
|
||||
mkdir -p "$DEVCONTAINER_DIR/config/aichat"
|
||||
mkdir -p "$DEVCONTAINER_DIR/config/ai_index"
|
||||
mkdir -p "$DEVCONTAINER_DIR/config/cargo-registry"
|
||||
mkdir -p "$DEVCONTAINER_DIR/config/cargo-git"
|
||||
mkdir -p "$DEVCONTAINER_DIR/config/cargo-bin"
|
||||
mkdir -p "$DEVCONTAINER_DIR/config/go-cache"
|
||||
mkdir -p "$DEVCONTAINER_DIR/config/go-bin"
|
||||
mkdir -p "$DEVCONTAINER_DIR/config/python-local"
|
||||
mkdir -p "$DEVCONTAINER_DIR/config/npm-cache"
|
||||
mkdir -p "$DEVCONTAINER_DIR/config/r-libs"
|
||||
|
||||
# --- devcontainer.json ---
|
||||
DEVCONTAINER_JSON="$DEVCONTAINER_DIR/devcontainer.json"
|
||||
if [[ -f "$DEVCONTAINER_JSON" ]]; then
|
||||
warning "devcontainer.json already exists, skipping"
|
||||
else
|
||||
fetch ".devcontainer/devcontainer.json" "$DEVCONTAINER_JSON"
|
||||
# Rename the service name to match the project
|
||||
sed -i.bak "s/\"name\": \"PMOCrazyCoder\"/\"name\": \"$(basename "$PROJECT_DIR")\"/" "$DEVCONTAINER_JSON"
|
||||
rm -f "$DEVCONTAINER_JSON.bak"
|
||||
info "Created devcontainer.json"
|
||||
fi
|
||||
|
||||
# --- docker-compose.yml ---
|
||||
COMPOSE_FILE="$DEVCONTAINER_DIR/docker-compose.yml"
|
||||
if [[ -f "$COMPOSE_FILE" ]]; then
|
||||
warning "docker-compose.yml already exists, skipping"
|
||||
else
|
||||
fetch ".devcontainer/docker-compose.yml" "$COMPOSE_FILE"
|
||||
# Patch LOCAL_LLM_API if overridden
|
||||
if [[ "$LOCAL_LLM_API" != "http://host.docker.internal:1248/v1" ]]; then
|
||||
sed -i.bak "s|http://host.docker.internal:1248/v1|${LOCAL_LLM_API}|g" "$COMPOSE_FILE"
|
||||
rm -f "$COMPOSE_FILE.bak"
|
||||
fi
|
||||
info "Created docker-compose.yml"
|
||||
fi
|
||||
|
||||
# --- .gitignore ---
|
||||
GITIGNORE="$PROJECT_DIR/.gitignore"
|
||||
if [[ -f "$GITIGNORE" ]]; then
|
||||
if grep -q "\.devcontainer/config/" "$GITIGNORE"; then
|
||||
warning ".gitignore already contains .devcontainer/config/, skipping"
|
||||
else
|
||||
printf '\n# PMOCrazyCoder devcontainer runtime config\n.devcontainer/config/\n' >> "$GITIGNORE"
|
||||
info "Updated .gitignore"
|
||||
fi
|
||||
else
|
||||
printf '# PMOCrazyCoder devcontainer runtime config\n.devcontainer/config/\n' > "$GITIGNORE"
|
||||
info "Created .gitignore"
|
||||
fi
|
||||
|
||||
echo
|
||||
info "Done. Next steps:"
|
||||
echo " 1. Open the project in VS Code / Zed / Cursor"
|
||||
echo " 2. Reopen in container (the image will be pulled from the registry)"
|
||||
echo " 3. Run /login in the Claude Agent panel to authenticate"
|
||||
echo
|
||||
info "To use a different local LLM API endpoint:"
|
||||
echo " LOCAL_LLM_API=http://myserver:1248/v1 bash setup-devcontainer.sh"
|
||||
@@ -1,2 +1 @@
|
||||
from .jj import *
|
||||
from .sandbox import *
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
from crazy_mcp import Context, mcp
|
||||
from jujutsu import jj_log
|
||||
from sandbox import get_active_project, get_project_path
|
||||
from jujutsu import jj_log, jj_new
|
||||
|
||||
|
||||
@mcp.tool(description="Get the commit history for a project")
|
||||
def jj_log_tool(project_name: str | None = None, ctx: Context = None) -> dict:
|
||||
def jj_log_tool(project_name: str | None = None, ctx: Context | None = None) -> dict:
|
||||
"""
|
||||
Get the commit history for a project.
|
||||
|
||||
@@ -15,19 +14,70 @@ def jj_log_tool(project_name: str | None = None, ctx: Context = None) -> dict:
|
||||
Returns:
|
||||
dict: The commit history as JSON structure
|
||||
"""
|
||||
# If no project name is provided, try to get the active project
|
||||
if project_name is None:
|
||||
if ctx is None:
|
||||
raise ValueError("ctx is required when project_name is None")
|
||||
|
||||
project_info = get_active_project(ctx.session_id)
|
||||
project_info = ctx.get_state("active_project")
|
||||
if project_info is None:
|
||||
raise ValueError("No active project set and no project name provided")
|
||||
project_path = project_info[1]
|
||||
else:
|
||||
project_path = get_project_path(project_name)
|
||||
project_path = project_info[1] if isinstance(project_info, tuple) else None
|
||||
if project_path is None:
|
||||
raise ValueError(f"Project '{project_name}' not found")
|
||||
raise ValueError("No project path found in active project")
|
||||
else:
|
||||
sandbox_root = "/sandbox"
|
||||
project_path = f"{sandbox_root}/{project_name}"
|
||||
|
||||
# Call the jj_log function from jujutsu module
|
||||
return jj_log(project_path)
|
||||
|
||||
|
||||
@mcp.tool(description="Create a new commit with AI-generated description")
|
||||
def jj_new_tool(
|
||||
project_name: str | None = None,
|
||||
revisions: list[str] | None = None,
|
||||
message: str | None = None,
|
||||
no_edit: bool = False,
|
||||
insert_after: str | None = None,
|
||||
insert_before: str | None = None,
|
||||
options: list[str] | None = None,
|
||||
ctx: Context | None = None,
|
||||
) -> str:
|
||||
"""
|
||||
Create a new commit after documenting the current change with AI.
|
||||
|
||||
Args:
|
||||
project_name (str, optional): The name of the project. If None, uses the active project.
|
||||
revisions (list[str], optional): List of parent revisions (default: [@])
|
||||
message (str, optional): The change description to use
|
||||
no_edit (bool): Do not edit the newly created change
|
||||
insert_after (str, optional): Insert the new change after the given commit(s)
|
||||
insert_before (str, optional): Insert the new change before the given commit(s)
|
||||
options (list[str], optional): List of additional options
|
||||
ctx (Context, optional): The MCP context object containing session information
|
||||
|
||||
Returns:
|
||||
str: Output of jj new command
|
||||
"""
|
||||
if project_name is None:
|
||||
if ctx is None:
|
||||
raise ValueError("ctx is required when project_name is None")
|
||||
|
||||
project_info = ctx.get_state("active_project")
|
||||
if project_info is None:
|
||||
raise ValueError("No active project set and no project name provided")
|
||||
project_path = project_info[1] if isinstance(project_info, tuple) else None
|
||||
if project_path is None:
|
||||
raise ValueError("No project path found in active project")
|
||||
else:
|
||||
sandbox_root = "/sandbox"
|
||||
project_path = f"{sandbox_root}/{project_name}"
|
||||
|
||||
return jj_new(
|
||||
revisions=revisions,
|
||||
message=message,
|
||||
no_edit=no_edit,
|
||||
insert_after=insert_after,
|
||||
insert_before=insert_before,
|
||||
options=options,
|
||||
working_dir=project_path,
|
||||
)
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
from crazy_mcp import Context, mcp
|
||||
from sandbox import (
|
||||
get_active_project,
|
||||
install_project,
|
||||
remove_project,
|
||||
sandboxed_project_list,
|
||||
set_active_project,
|
||||
)
|
||||
|
||||
|
||||
@mcp.tool(
|
||||
description="Clone a Git repository into the sandbox. Note: Access to the cloned project is only possible through MCP tools of this server. WARNING: This operation creates a sandboxed environment that prevents direct filesystem access to the project contents. Any attempt to access project files outside of the MCP tools will be blocked by security restrictions."
|
||||
)
|
||||
def install_project_tool(url: str, project_name: str = None) -> str:
|
||||
"""
|
||||
Install a Git project into the sandbox environment.
|
||||
|
||||
Args:
|
||||
url: The Git repository URL to clone
|
||||
project_name: Optional project name (if None, derived from URL)
|
||||
|
||||
Returns:
|
||||
str: Confirmation message with project name
|
||||
"""
|
||||
project_name = install_project(url, project_name)
|
||||
return f"Project '{project_name}' installed successfully in sandbox"
|
||||
|
||||
|
||||
@mcp.tool(
|
||||
description="Remove a project from the sandbox. Note: Access to the cloned project is only possible through MCP tools of this server. WARNING: This operation removes the entire project sandboxed environment and all associated security restrictions will be enforced."
|
||||
)
|
||||
def remove_project_tool(project_name: str) -> str:
|
||||
"""
|
||||
Remove a project from the sandbox environment.
|
||||
|
||||
Args:
|
||||
project_name (str): The name of the project to remove
|
||||
|
||||
Returns:
|
||||
str: Confirmation message with project name
|
||||
"""
|
||||
success = remove_project(project_name)
|
||||
if success:
|
||||
return f"Project '{project_name}' removed successfully from sandbox"
|
||||
else:
|
||||
return f"Failed to remove project '{project_name}' from sandbox"
|
||||
|
||||
|
||||
@mcp.tool(
|
||||
description="List all projects available in the sandbox. Note: Direct filesystem access to project contents is forbidden. All project interactions must be done through MCP tools."
|
||||
)
|
||||
def list_sandboxed_projects() -> list:
|
||||
"""
|
||||
Get a list of all projects available in the sandbox.
|
||||
|
||||
Returns:
|
||||
list: A list of project names
|
||||
"""
|
||||
return sandboxed_project_list()
|
||||
|
||||
|
||||
@mcp.tool(description="Set the active project for a given session ID")
|
||||
def set_active_project_tool(project_name: str, ctx: Context) -> bool:
|
||||
"""
|
||||
Set the active project for a given session ID.
|
||||
|
||||
Args:
|
||||
project_name (str): The name of the project to set as active
|
||||
ctx (Context): The MCP context object containing session information
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False if the project doesn't exist
|
||||
"""
|
||||
return set_active_project(ctx.session_id, project_name)
|
||||
|
||||
|
||||
@mcp.tool(description="Get the active project for a given session ID")
|
||||
def get_active_project_tool(ctx: Context) -> tuple[str, str] | None:
|
||||
"""
|
||||
Get the active project for a given session ID.
|
||||
|
||||
Args:
|
||||
ctx (Context): The MCP context object containing session information
|
||||
|
||||
Returns:
|
||||
tuple: (project_name, project_path) if session exists, None otherwise
|
||||
"""
|
||||
project_info = get_active_project(ctx.session_id)
|
||||
return project_info
|
||||
@@ -1,8 +1,8 @@
|
||||
import json
|
||||
import os
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
from typing import Dict, List, Optional
|
||||
import urllib.request
|
||||
from typing import Dict
|
||||
|
||||
|
||||
def structure_to_json(text: str, schema: Dict) -> Dict:
|
||||
@@ -17,7 +17,9 @@ def structure_to_json(text: str, schema: Dict) -> Dict:
|
||||
dict: The parsed JSON object
|
||||
"""
|
||||
# Get the API URL from environment variable
|
||||
local_llm_api = os.environ.get("LOCAL_LLM_API", "http://host.docker.internal:1248/v1")
|
||||
local_llm_api = os.environ.get(
|
||||
"LOCAL_LLM_API", "http://host.docker.internal:1248/v1"
|
||||
)
|
||||
|
||||
# Format the schema as JSON string
|
||||
schema_json = json.dumps(schema, indent=2)
|
||||
@@ -34,9 +36,7 @@ Schema:
|
||||
# Build the request body
|
||||
request_body = {
|
||||
"model": "qwen3-coder",
|
||||
"messages": [
|
||||
{"role": "user", "content": prompt_text}
|
||||
]
|
||||
"messages": [{"role": "user", "content": prompt_text}],
|
||||
}
|
||||
|
||||
# Build the URL
|
||||
@@ -45,10 +45,7 @@ Schema:
|
||||
# Create the request
|
||||
data = json.dumps(request_body).encode("utf-8")
|
||||
req = urllib.request.Request(
|
||||
url,
|
||||
data=data,
|
||||
headers={"Content-Type": "application/json"},
|
||||
method="POST"
|
||||
url, data=data, headers={"Content-Type": "application/json"}, method="POST"
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -73,4 +70,7 @@ Schema:
|
||||
# Parse the JSON content
|
||||
return json.loads(clean_content)
|
||||
except (json.JSONDecodeError, KeyError, IndexError) as e:
|
||||
return {"error": f"Failed to parse JSON: {e}", "raw_response": json.dumps(result)}
|
||||
return {
|
||||
"error": f"Failed to parse JSON: {e}",
|
||||
"raw_response": json.dumps(result),
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import unittest
|
||||
from unittest.mock import patch, MagicMock
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
sys.path.insert(0, "/workspace/src")
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import os
|
||||
import shlex
|
||||
from typing import Optional
|
||||
|
||||
from json_extract import structure_to_json
|
||||
from jujutsu.command import jj_log as jj_log_command
|
||||
from jujutsu.command import jj_diff
|
||||
from jujutsu.command import jj_log as jj_log_command
|
||||
from jujutsu.command import jj_new as jj_new_command
|
||||
|
||||
from .command import jj
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
from typing import List, Optional
|
||||
|
||||
Reference in New Issue
Block a user