@profoundlogic/coderflow-server 0.4.1 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/README.md +1 -1
- package/dist/base-image/Dockerfile +2 -1
- package/dist/base-image/entrypoint.sh +11 -1
- package/dist/base-image/rewind-files.sh +197 -0
- package/dist/base-image/sync-repos.sh +53 -3
- package/dist/coder-server.js +1 -1
- package/dist/config.js +1 -1
- package/dist/lib/agent-keepalive.js +1 -1
- package/dist/lib/agent-models.js +1 -1
- package/dist/lib/api-keys.js +1 -1
- package/dist/lib/apiKeys.js +1 -1
- package/dist/lib/app-server-ports.js +1 -1
- package/dist/lib/auto-judge.js +1 -1
- package/dist/lib/basic-auth.js +1 -1
- package/dist/lib/build-history.js +1 -1
- package/dist/lib/build-output-service.js +1 -1
- package/dist/lib/build-scheduler.js +1 -1
- package/dist/lib/build-service.js +1 -1
- package/dist/lib/ca-certificates.js +1 -1
- package/dist/lib/claude-oauth-refresh.js +1 -1
- package/dist/lib/cli/build.js +1 -1
- package/dist/lib/cli/config-command.js +1 -1
- package/dist/lib/cli/config.js +1 -1
- package/dist/lib/cli/create-user.js +1 -1
- package/dist/lib/cli/init.js +1 -1
- package/dist/lib/cli/jira.js +1 -1
- package/dist/lib/cli/license.js +1 -1
- package/dist/lib/cli/server-manager.js +1 -1
- package/dist/lib/config-migration.js +1 -1
- package/dist/lib/container-credential-sync.js +1 -1
- package/dist/lib/container-tokens.js +1 -1
- package/dist/lib/data-dir.js +1 -1
- package/dist/lib/deployment-history.js +1 -1
- package/dist/lib/deployment-service.js +1 -1
- package/dist/lib/docker-utils.js +1 -1
- package/dist/lib/email.js +1 -1
- package/dist/lib/emailTemplates.js +1 -1
- package/dist/lib/entitlement.js +1 -1
- package/dist/lib/fetch-utils.js +1 -1
- package/dist/lib/git-askpass.sh +16 -0
- package/dist/lib/git-commit-details-route.js +1 -1
- package/dist/lib/git-history-diff-guardrails.js +1 -1
- package/dist/lib/git-provider-service.js +1 -1
- package/dist/lib/git-provider-setup/github-setup-handler.js +1 -1
- package/dist/lib/git-provider-setup/index.js +1 -1
- package/dist/lib/git-provider-setup/setup-factory.js +1 -1
- package/dist/lib/git-provider-setup/setup-interface.js +1 -1
- package/dist/lib/git-providers/azure-devops-provider.js +1 -1
- package/dist/lib/git-providers/github-app-provider.js +1 -1
- package/dist/lib/git-providers/index.js +1 -1
- package/dist/lib/git-providers/provider-factory.js +1 -1
- package/dist/lib/git-providers/provider-interface.js +1 -1
- package/dist/lib/github-urls.js +1 -1
- package/dist/lib/group-objective-linking.js +1 -1
- package/dist/lib/jira-client.js +1 -1
- package/dist/lib/judge-blinding.js +1 -1
- package/dist/lib/logger.js +1 -1
- package/dist/lib/model-fetcher.js +1 -1
- package/dist/lib/notifications.js +1 -1
- package/dist/lib/objective-context.js +1 -0
- package/dist/lib/oidc-auth.js +1 -1
- package/dist/lib/oidc-device-flow.js +1 -1
- package/dist/lib/passwordTokens.js +1 -1
- package/dist/lib/pin-cascade.js +1 -1
- package/dist/lib/provider-accounts.js +1 -1
- package/dist/lib/provider-oauth.js +1 -1
- package/dist/lib/provider-profile.js +1 -1
- package/dist/lib/provider-token-refresh.js +1 -1
- package/dist/lib/request-url.js +1 -1
- package/dist/lib/rewind.js +1 -1
- package/dist/lib/roles.js +1 -1
- package/dist/lib/secrets.js +1 -1
- package/dist/lib/setup-repo-git-auth.js +1 -1
- package/dist/lib/state-capture.js +1 -1
- package/dist/lib/static-files.js +1 -1
- package/dist/lib/task-name-format.js +1 -1
- package/dist/lib/task-name-generator.js +1 -1
- package/dist/lib/user-git-oauth.js +1 -1
- package/dist/lib/user-git-tokens.js +1 -1
- package/dist/lib/users.js +1 -1
- package/dist/middleware/requireAuth.js +1 -1
- package/dist/middleware/requireInit.js +1 -1
- package/dist/middleware/requirePermission.js +1 -1
- package/dist/package.json +2 -1
- package/dist/routes/apiKeys.js +1 -1
- package/dist/routes/auth-oidc.js +1 -1
- package/dist/routes/auth.js +1 -1
- package/dist/routes/build.js +1 -1
- package/dist/routes/containers.js +1 -1
- package/dist/routes/deploy-task.js +1 -1
- package/dist/routes/environment-management.js +1 -1
- package/dist/routes/environments.js +1 -1
- package/dist/routes/external-skills.js +1 -1
- package/dist/routes/git-credentials.js +1 -1
- package/dist/routes/git-oauth.js +1 -1
- package/dist/routes/git-provider-setup.js +1 -1
- package/dist/routes/health.js +1 -1
- package/dist/routes/jira.js +1 -1
- package/dist/routes/objective-management.js +1 -1
- package/dist/routes/password.js +1 -1
- package/dist/routes/prompt.js +1 -1
- package/dist/routes/provider-auth.js +1 -1
- package/dist/routes/qa.js +1 -1
- package/dist/routes/settings.js +1 -1
- package/dist/routes/skill-management.js +1 -1
- package/dist/routes/skills.js +1 -1
- package/dist/routes/tasks.js +1 -1
- package/dist/routes/templates.js +1 -1
- package/dist/routes/test-task.js +1 -1
- package/dist/routes/test.js +1 -1
- package/dist/routes/users.js +1 -1
- package/dist/routes/visualizations.js +1 -1
- package/dist/scripts/create-user.js +1 -1
- package/dist/scripts/migrate-config-to-data-dir.js +1 -1
- package/dist/shipped-skills/objective-management/SKILL.md +83 -0
- package/dist/start.js +1 -1
- package/dist/web-ui/public/activity-detail-modal.js +1 -1
- package/dist/web-ui/public/activity-feed.js +1 -1
- package/dist/web-ui/public/activity-formatters.js +1 -1
- package/dist/web-ui/public/agent-event-parser.js +1 -1
- package/dist/web-ui/public/app.js +1 -1
- package/dist/web-ui/public/approve-dialog.js +1 -1
- package/dist/web-ui/public/comments-widget.js +1 -1
- package/dist/web-ui/public/diff-utils.js +1 -1
- package/dist/web-ui/public/docs/admin/git-providers.md +10 -5
- package/dist/web-ui/public/docs/admin/installation.md +1 -1
- package/dist/web-ui/public/environments.css +6 -0
- package/dist/web-ui/public/environments.html +20 -0
- package/dist/web-ui/public/environments.js +1 -1
- package/dist/web-ui/public/feedback-widget.js +1 -1
- package/dist/web-ui/public/git-history-lazy-utils.js +1 -1
- package/dist/web-ui/public/git-history.js +1 -1
- package/dist/web-ui/public/git-status.js +1 -1
- package/dist/web-ui/public/index.html +21 -0
- package/dist/web-ui/public/index.js +1 -1
- package/dist/web-ui/public/login.js +1 -1
- package/dist/web-ui/public/markdown-editor.js +1 -1
- package/dist/web-ui/public/markdown-file-editor.js +1 -1
- package/dist/web-ui/public/modal-maximize.js +1 -1
- package/dist/web-ui/public/notifications.js +1 -1
- package/dist/web-ui/public/pr-dialog.js +1 -1
- package/dist/web-ui/public/server-health.js +1 -1
- package/dist/web-ui/public/settings.html +22 -1
- package/dist/web-ui/public/settings.js +1 -1
- package/dist/web-ui/public/setup-password.js +1 -1
- package/dist/web-ui/public/skills.css +6 -0
- package/dist/web-ui/public/skills.html +20 -0
- package/dist/web-ui/public/skills.js +1 -1
- package/dist/web-ui/public/sse-client.js +1 -1
- package/dist/web-ui/public/sse-shared-worker.js +1 -1
- package/dist/web-ui/public/styles.css +160 -0
- package/dist/web-ui/public/task.html +32 -1
- package/dist/web-ui/public/task.js +1 -1
- package/dist/web-ui/public/terminal.js +1 -1
- package/dist/web-ui/public/theme.js +1 -1
- package/dist/web-ui/public/users.js +1 -1
- package/dist/web-ui/public/variant-grouping.js +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -111,7 +111,7 @@ This creates a `mycompany-coder-setup` directory with the required structure and
|
|
|
111
111
|
#### Install License
|
|
112
112
|
|
|
113
113
|
```bash
|
|
114
|
-
coder-server license set <your-license-key>
|
|
114
|
+
coder-server license set <your-license-key>
|
|
115
115
|
```
|
|
116
116
|
|
|
117
117
|
#### Create Admin User
|
package/dist/README.md
CHANGED
|
@@ -111,7 +111,7 @@ This creates a `mycompany-coder-setup` directory with the required structure and
|
|
|
111
111
|
#### Install License
|
|
112
112
|
|
|
113
113
|
```bash
|
|
114
|
-
coder-server license set <your-license-key>
|
|
114
|
+
coder-server license set <your-license-key>
|
|
115
115
|
```
|
|
116
116
|
|
|
117
117
|
#### Create Admin User
|
|
@@ -176,11 +176,12 @@ WORKDIR /workspace
|
|
|
176
176
|
# Copy entrypoint script and AI agent wrapper
|
|
177
177
|
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
|
|
178
178
|
COPY sync-repos.sh /usr/local/bin/sync-repos.sh
|
|
179
|
+
COPY rewind-files.sh /usr/local/bin/rewind-files.sh
|
|
179
180
|
COPY agent-wrapper.sh /usr/local/bin/agent-wrapper.sh
|
|
180
181
|
COPY start-code-server.sh /usr/local/bin/start-code-server.sh
|
|
181
182
|
COPY apply-local-state.sh /usr/local/bin/apply-local-state.sh
|
|
182
183
|
COPY coder-git-credential-helper /usr/local/bin/coder-git-credential-helper
|
|
183
|
-
RUN chmod +x /usr/local/bin/entrypoint.sh /usr/local/bin/sync-repos.sh /usr/local/bin/agent-wrapper.sh /usr/local/bin/start-code-server.sh /usr/local/bin/apply-local-state.sh /usr/local/bin/coder-git-credential-helper
|
|
184
|
+
RUN chmod +x /usr/local/bin/entrypoint.sh /usr/local/bin/sync-repos.sh /usr/local/bin/rewind-files.sh /usr/local/bin/agent-wrapper.sh /usr/local/bin/start-code-server.sh /usr/local/bin/apply-local-state.sh /usr/local/bin/coder-git-credential-helper
|
|
184
185
|
|
|
185
186
|
# Expose code-server port
|
|
186
187
|
EXPOSE 8080
|
|
@@ -715,7 +715,17 @@ generate_task_json() {
|
|
|
715
715
|
escaped_command="${escaped_command//$'\r'/\\r}" # Escape carriage returns
|
|
716
716
|
escaped_command="${escaped_command//$'\t'/\\t}" # Escape tabs
|
|
717
717
|
|
|
718
|
+
# Preserve turn_patches accumulated by auto-sync from previous runs
|
|
719
|
+
local existing_turn_patches='null'
|
|
720
|
+
if [ -f "$TASK_OUTPUT_DIR/task.json" ]; then
|
|
721
|
+
existing_turn_patches=$(jq -c '.turn_patches // null' "$TASK_OUTPUT_DIR/task.json" 2>/dev/null || echo 'null')
|
|
722
|
+
fi
|
|
723
|
+
|
|
718
724
|
# Create task.json in the output directory
|
|
725
|
+
local turn_patches_field=""
|
|
726
|
+
if [ "$existing_turn_patches" != "null" ] && [ -n "$existing_turn_patches" ]; then
|
|
727
|
+
turn_patches_field=',"turn_patches": '"$existing_turn_patches"
|
|
728
|
+
fi
|
|
719
729
|
cat > "$TASK_OUTPUT_DIR/task.json" <<EOF
|
|
720
730
|
{
|
|
721
731
|
"task_id": "$TASK_ID",
|
|
@@ -733,7 +743,7 @@ generate_task_json() {
|
|
|
733
743
|
"log_path": "log.txt",
|
|
734
744
|
"instructions_path": "task-instructions.md",
|
|
735
745
|
"commit_message": "$commit_message",
|
|
736
|
-
"repos_changed": $repos_changed
|
|
746
|
+
"repos_changed": $repos_changed$turn_patches_field
|
|
737
747
|
}
|
|
738
748
|
EOF
|
|
739
749
|
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Rewind workspace files to a specific turn snapshot.
|
|
3
|
+
# Resets each repository to committed state, then reapplies the turn patch.
|
|
4
|
+
|
|
5
|
+
set -o pipefail
|
|
6
|
+
|
|
7
|
+
TASK_OUTPUT_DIR="${TASK_OUTPUT_DIR:-/task-output}"
|
|
8
|
+
WORKSPACE_DIR="${WORKSPACE_DIR:-/workspace}"
|
|
9
|
+
TARGET_TURN="${TARGET_TURN:-}"
|
|
10
|
+
turn_dir="$TASK_OUTPUT_DIR/patches/turn-$TARGET_TURN"
|
|
11
|
+
|
|
12
|
+
if ! [[ "$TARGET_TURN" =~ ^[0-9]+$ ]]; then
|
|
13
|
+
echo "{\"target_turn\":0,\"success\":false,\"error\":\"TARGET_TURN must be a non-negative integer\",\"repos\":[]}"
|
|
14
|
+
exit 1
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
temp_dir=$(mktemp -d)
|
|
18
|
+
trap "rm -rf $temp_dir" EXIT
|
|
19
|
+
|
|
20
|
+
overall_success=true
|
|
21
|
+
repo_index=0
|
|
22
|
+
|
|
23
|
+
emit_repo_result() {
|
|
24
|
+
local output_file="$1"
|
|
25
|
+
local repo_name="$2"
|
|
26
|
+
local repo_path="$3"
|
|
27
|
+
local has_patch="$4"
|
|
28
|
+
local applied="$5"
|
|
29
|
+
local success="$6"
|
|
30
|
+
local error_message="$7"
|
|
31
|
+
local files_changed="$8"
|
|
32
|
+
local lines_added="$9"
|
|
33
|
+
local lines_deleted="${10}"
|
|
34
|
+
|
|
35
|
+
jq -n \
|
|
36
|
+
--arg name "$repo_name" \
|
|
37
|
+
--arg path "$repo_path" \
|
|
38
|
+
--argjson has_patch "$has_patch" \
|
|
39
|
+
--argjson applied "$applied" \
|
|
40
|
+
--argjson success "$success" \
|
|
41
|
+
--arg error "$error_message" \
|
|
42
|
+
--argjson files_changed "$files_changed" \
|
|
43
|
+
--argjson lines_added "$lines_added" \
|
|
44
|
+
--argjson lines_deleted "$lines_deleted" \
|
|
45
|
+
'{
|
|
46
|
+
name: $name,
|
|
47
|
+
path: $path,
|
|
48
|
+
has_patch: $has_patch,
|
|
49
|
+
applied: $applied,
|
|
50
|
+
success: $success,
|
|
51
|
+
error: ($error | if . == "" then null else . end),
|
|
52
|
+
files_changed: $files_changed,
|
|
53
|
+
lines_added: $lines_added,
|
|
54
|
+
lines_deleted: $lines_deleted
|
|
55
|
+
}' > "$output_file"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
process_repo() {
|
|
59
|
+
local repo_name="$1"
|
|
60
|
+
local repo_path="$2"
|
|
61
|
+
local output_file="$3"
|
|
62
|
+
local patch_file="$turn_dir/$repo_name.patch"
|
|
63
|
+
|
|
64
|
+
local has_patch=false
|
|
65
|
+
local applied=false
|
|
66
|
+
local success=true
|
|
67
|
+
local error_message=""
|
|
68
|
+
local files_changed=0
|
|
69
|
+
local lines_added=0
|
|
70
|
+
local lines_deleted=0
|
|
71
|
+
|
|
72
|
+
if [ ! -d "$repo_path/.git" ]; then
|
|
73
|
+
success=false
|
|
74
|
+
error_message="Repository is missing .git directory"
|
|
75
|
+
emit_repo_result "$output_file" "$repo_name" "$repo_path" "$has_patch" "$applied" "$success" "$error_message" "$files_changed" "$lines_added" "$lines_deleted"
|
|
76
|
+
return 1
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
cd "$repo_path" || {
|
|
80
|
+
success=false
|
|
81
|
+
error_message="Failed to access repository directory"
|
|
82
|
+
emit_repo_result "$output_file" "$repo_name" "$repo_path" "$has_patch" "$applied" "$success" "$error_message" "$files_changed" "$lines_added" "$lines_deleted"
|
|
83
|
+
return 1
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if ! git reset --hard HEAD >/dev/null 2>&1; then
|
|
87
|
+
success=false
|
|
88
|
+
error_message="git reset --hard failed"
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
if $success && ! git clean -fd >/dev/null 2>&1; then
|
|
92
|
+
success=false
|
|
93
|
+
error_message="git clean -fd failed"
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
if $success && [ -f "$patch_file" ] && [ -s "$patch_file" ]; then
|
|
97
|
+
has_patch=true
|
|
98
|
+
if git apply --whitespace=nowarn "$patch_file" >/dev/null 2>&1; then
|
|
99
|
+
applied=true
|
|
100
|
+
else
|
|
101
|
+
success=false
|
|
102
|
+
error_message="git apply failed for turn patch"
|
|
103
|
+
fi
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
if $success && ! git add -A >/dev/null 2>&1; then
|
|
107
|
+
success=false
|
|
108
|
+
error_message="git add -A failed"
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
if $success; then
|
|
112
|
+
local stat_output
|
|
113
|
+
stat_output=$(git diff --cached --stat 2>/dev/null | tail -1)
|
|
114
|
+
if [ -n "$stat_output" ]; then
|
|
115
|
+
files_changed=$(echo "$stat_output" | grep -oE '[0-9]+ file' | grep -oE '[0-9]+' || echo "0")
|
|
116
|
+
lines_added=$(echo "$stat_output" | grep -oE '[0-9]+ insertion' | grep -oE '[0-9]+' || echo "0")
|
|
117
|
+
lines_deleted=$(echo "$stat_output" | grep -oE '[0-9]+ deletion' | grep -oE '[0-9]+' || echo "0")
|
|
118
|
+
fi
|
|
119
|
+
files_changed=${files_changed:-0}
|
|
120
|
+
lines_added=${lines_added:-0}
|
|
121
|
+
lines_deleted=${lines_deleted:-0}
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
emit_repo_result "$output_file" "$repo_name" "$repo_path" "$has_patch" "$applied" "$success" "$error_message" "$files_changed" "$lines_added" "$lines_deleted"
|
|
125
|
+
$success
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
process_repo_entry() {
|
|
129
|
+
local repo_name="$1"
|
|
130
|
+
local repo_path="$2"
|
|
131
|
+
local output_file="$temp_dir/repo_$repo_index.json"
|
|
132
|
+
|
|
133
|
+
process_repo "$repo_name" "$repo_path" "$output_file" || overall_success=false
|
|
134
|
+
repo_index=$((repo_index + 1))
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
# Iterate configured repositories, or scan workspace if no config was provided.
|
|
138
|
+
if [ -n "$REPOS_CONFIG" ]; then
|
|
139
|
+
repo_count=$(echo "$REPOS_CONFIG" | jq 'length' 2>/dev/null)
|
|
140
|
+
if [ -n "$repo_count" ] && [ "$repo_count" -gt 0 ]; then
|
|
141
|
+
for index in $(seq 0 $((repo_count - 1))); do
|
|
142
|
+
repo_json=$(echo "$REPOS_CONFIG" | jq -c ".[$index]" 2>/dev/null)
|
|
143
|
+
[ -z "$repo_json" ] || [ "$repo_json" = "null" ] && continue
|
|
144
|
+
|
|
145
|
+
repo_name=$(echo "$repo_json" | jq -r 'if type == "object" then (.name // empty) else . end' 2>/dev/null)
|
|
146
|
+
repo_path_rel=$(echo "$repo_json" | jq -r 'if type == "object" then (.path // empty) else empty end' 2>/dev/null)
|
|
147
|
+
[ -z "$repo_name" ] || [ "$repo_name" = "null" ] && continue
|
|
148
|
+
|
|
149
|
+
if [ -n "$repo_path_rel" ] && [ "$repo_path_rel" != "null" ]; then
|
|
150
|
+
repo_path="$WORKSPACE_DIR/$repo_path_rel"
|
|
151
|
+
else
|
|
152
|
+
repo_path="$WORKSPACE_DIR/$repo_name"
|
|
153
|
+
fi
|
|
154
|
+
|
|
155
|
+
process_repo_entry "$repo_name" "$repo_path"
|
|
156
|
+
done
|
|
157
|
+
fi
|
|
158
|
+
else
|
|
159
|
+
for repo_path in "$WORKSPACE_DIR"/*; do
|
|
160
|
+
if [ -d "$repo_path/.git" ]; then
|
|
161
|
+
repo_name=$(basename "$repo_path")
|
|
162
|
+
process_repo_entry "$repo_name" "$repo_path"
|
|
163
|
+
fi
|
|
164
|
+
done
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# Collect repo results into one array
|
|
168
|
+
repos_json="["
|
|
169
|
+
first=true
|
|
170
|
+
for f in "$temp_dir"/repo_*.json; do
|
|
171
|
+
[ -f "$f" ] && [ -s "$f" ] || continue
|
|
172
|
+
if $first; then
|
|
173
|
+
first=false
|
|
174
|
+
else
|
|
175
|
+
repos_json="$repos_json,"
|
|
176
|
+
fi
|
|
177
|
+
repos_json="$repos_json$(cat "$f")"
|
|
178
|
+
done
|
|
179
|
+
repos_json="$repos_json]"
|
|
180
|
+
|
|
181
|
+
if $overall_success; then
|
|
182
|
+
overall_success_json=true
|
|
183
|
+
else
|
|
184
|
+
overall_success_json=false
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
jq -n \
|
|
188
|
+
--argjson target_turn "$TARGET_TURN" \
|
|
189
|
+
--argjson success "$overall_success_json" \
|
|
190
|
+
--argjson repos "$repos_json" \
|
|
191
|
+
'{
|
|
192
|
+
target_turn: $target_turn,
|
|
193
|
+
success: $success,
|
|
194
|
+
repos: $repos
|
|
195
|
+
}' > "$TASK_OUTPUT_DIR/rewind-result.json"
|
|
196
|
+
|
|
197
|
+
cat "$TASK_OUTPUT_DIR/rewind-result.json"
|
|
@@ -8,6 +8,7 @@ set -o pipefail
|
|
|
8
8
|
TASK_OUTPUT_DIR="${TASK_OUTPUT_DIR:-/task-output}"
|
|
9
9
|
WORKSPACE_DIR="${WORKSPACE_DIR:-/workspace}"
|
|
10
10
|
patches_dir="$TASK_OUTPUT_DIR/patches"
|
|
11
|
+
TURN_NUMBER="${TURN_NUMBER:-}"
|
|
11
12
|
|
|
12
13
|
# Simple log function
|
|
13
14
|
log() {
|
|
@@ -152,9 +153,58 @@ for f in "$temp_dir"/repo_*.json; do
|
|
|
152
153
|
done
|
|
153
154
|
result="$result]"
|
|
154
155
|
|
|
155
|
-
#
|
|
156
|
+
# Optional per-turn snapshot copy for rewind history
|
|
157
|
+
turn_number_valid=false
|
|
158
|
+
if [[ "$TURN_NUMBER" =~ ^[0-9]+$ ]]; then
|
|
159
|
+
turn_number_valid=true
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
if $turn_number_valid; then
|
|
163
|
+
turn_dir="$patches_dir/turn-$TURN_NUMBER"
|
|
164
|
+
mkdir -p "$turn_dir"
|
|
165
|
+
find "$turn_dir" -maxdepth 1 -type f -name '*.patch' -delete 2>/dev/null || true
|
|
166
|
+
|
|
167
|
+
while IFS= read -r patch_file; do
|
|
168
|
+
[ -z "$patch_file" ] && continue
|
|
169
|
+
[ -f "$patches_dir/$patch_file" ] || continue
|
|
170
|
+
cp "$patches_dir/$patch_file" "$turn_dir/$patch_file"
|
|
171
|
+
done < <(echo "$result" | jq -r '.[]?.patch_file' 2>/dev/null)
|
|
172
|
+
fi
|
|
173
|
+
|
|
174
|
+
# Update task.json with repos_changed and stats (create if it doesn't exist)
|
|
175
|
+
# This ensures sync results are readable by the server even for staged/running tasks
|
|
176
|
+
existing_json='{}'
|
|
156
177
|
if [ -f "$TASK_OUTPUT_DIR/task.json" ]; then
|
|
157
|
-
|
|
178
|
+
existing_json=$(cat "$TASK_OUTPUT_DIR/task.json")
|
|
179
|
+
fi
|
|
180
|
+
|
|
181
|
+
turn_timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
182
|
+
if $turn_number_valid; then
|
|
183
|
+
echo "$existing_json" | jq --argjson repos "$result" --argjson turn "$TURN_NUMBER" --arg timestamp "$turn_timestamp" '
|
|
184
|
+
.repos_changed = $repos |
|
|
185
|
+
.stats = {
|
|
186
|
+
repositories: ($repos | length),
|
|
187
|
+
filesChanged: ([$repos[].files_changed] | add // 0),
|
|
188
|
+
linesAdded: ([$repos[].lines_added] | add // 0),
|
|
189
|
+
linesDeleted: ([$repos[].lines_deleted] | add // 0)
|
|
190
|
+
} |
|
|
191
|
+
.turn_patches = (
|
|
192
|
+
((.turn_patches // []) | map(select((.turn // -1) != $turn))) + [{
|
|
193
|
+
turn: $turn,
|
|
194
|
+
repos_changed: ($repos | map(.name)),
|
|
195
|
+
stats: {
|
|
196
|
+
repositories: ($repos | length),
|
|
197
|
+
filesChanged: ([$repos[].files_changed] | add // 0),
|
|
198
|
+
linesAdded: ([$repos[].lines_added] | add // 0),
|
|
199
|
+
linesDeleted: ([$repos[].lines_deleted] | add // 0)
|
|
200
|
+
},
|
|
201
|
+
timestamp: $timestamp
|
|
202
|
+
}] | sort_by(.turn)
|
|
203
|
+
)
|
|
204
|
+
' > "$TASK_OUTPUT_DIR/task.json.tmp" && \
|
|
205
|
+
mv "$TASK_OUTPUT_DIR/task.json.tmp" "$TASK_OUTPUT_DIR/task.json"
|
|
206
|
+
else
|
|
207
|
+
echo "$existing_json" | jq --argjson repos "$result" '
|
|
158
208
|
.repos_changed = $repos |
|
|
159
209
|
.stats = {
|
|
160
210
|
repositories: ($repos | length),
|
|
@@ -162,7 +212,7 @@ if [ -f "$TASK_OUTPUT_DIR/task.json" ]; then
|
|
|
162
212
|
linesAdded: ([$repos[].lines_added] | add // 0),
|
|
163
213
|
linesDeleted: ([$repos[].lines_deleted] | add // 0)
|
|
164
214
|
}
|
|
165
|
-
'
|
|
215
|
+
' > "$TASK_OUTPUT_DIR/task.json.tmp" && \
|
|
166
216
|
mv "$TASK_OUTPUT_DIR/task.json.tmp" "$TASK_OUTPUT_DIR/task.json"
|
|
167
217
|
fi
|
|
168
218
|
|