cclaw-cli 0.46.5 → 0.46.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/content/observe.d.ts +0 -1
- package/dist/content/observe.js +0 -254
- package/package.json +1 -1
|
@@ -15,7 +15,6 @@ export interface WorkflowGuardOptions {
|
|
|
15
15
|
tddTestGlobs?: string[];
|
|
16
16
|
}
|
|
17
17
|
export declare function workflowGuardScript(options?: WorkflowGuardOptions): string;
|
|
18
|
-
export declare function observeScript(): string;
|
|
19
18
|
export declare function contextMonitorScript(): string;
|
|
20
19
|
export declare function summarizeObservationsRuntimeModule(): string;
|
|
21
20
|
export declare function summarizeObservationsScript(): string;
|
package/dist/content/observe.js
CHANGED
|
@@ -693,260 +693,6 @@ if [ -n "$REASONS" ]; then
|
|
|
693
693
|
printf '[cclaw] %s\n' "$NOTE" >&2
|
|
694
694
|
fi
|
|
695
695
|
|
|
696
|
-
exit 0
|
|
697
|
-
`;
|
|
698
|
-
}
|
|
699
|
-
export function observeScript() {
|
|
700
|
-
return `#!/usr/bin/env bash
|
|
701
|
-
# cclaw observe hook — generated by cclaw sync
|
|
702
|
-
# Captures PreToolUse/PostToolUse events to ${RUNTIME_ROOT}/observations.jsonl
|
|
703
|
-
# Reads hook JSON from stdin, extracts tool + truncated I/O, appends JSONL.
|
|
704
|
-
# Always exits 0 to never block the agent.
|
|
705
|
-
set -uo pipefail
|
|
706
|
-
|
|
707
|
-
# Phase: "pre" or "post" passed as $1 by the hook runner
|
|
708
|
-
PHASE="\${1:-post}"
|
|
709
|
-
|
|
710
|
-
${RUNTIME_SHELL_DETECT_ROOT}
|
|
711
|
-
|
|
712
|
-
OBS_FILE="$ROOT/${RUNTIME_ROOT}/observations.jsonl"
|
|
713
|
-
STATE_FILE="$ROOT/${RUNTIME_ROOT}/state/flow-state.json"
|
|
714
|
-
ACTIVITY_FILE="$ROOT/${RUNTIME_ROOT}/state/stage-activity.jsonl"
|
|
715
|
-
LOCK_DIR="$ROOT/${RUNTIME_ROOT}/state/.observe.lock"
|
|
716
|
-
MAX_LEN=2000
|
|
717
|
-
|
|
718
|
-
# Guard: skip if disabled or observations dir missing
|
|
719
|
-
[ -f "$ROOT/${RUNTIME_ROOT}/.observe-disabled" ] && exit 0
|
|
720
|
-
[ -d "$ROOT/${RUNTIME_ROOT}" ] || exit 0
|
|
721
|
-
mkdir -p "$ROOT/${RUNTIME_ROOT}/state" 2>/dev/null || true
|
|
722
|
-
|
|
723
|
-
escape_json() {
|
|
724
|
-
local str="$1"
|
|
725
|
-
str=\${str//\\\\/\\\\\\\\}
|
|
726
|
-
str=\${str//\\"/\\\\\\"}
|
|
727
|
-
str=\${str//$'\\t'/\\\\t}
|
|
728
|
-
str=\${str//$'\\n'/\\\\n}
|
|
729
|
-
printf '%s' "$str"
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
acquire_lock() {
|
|
733
|
-
local attempt=0
|
|
734
|
-
while ! mkdir "$LOCK_DIR" 2>/dev/null; do
|
|
735
|
-
attempt=$((attempt + 1))
|
|
736
|
-
if [ "$attempt" -ge 200 ]; then
|
|
737
|
-
return 1
|
|
738
|
-
fi
|
|
739
|
-
sleep 0.02
|
|
740
|
-
done
|
|
741
|
-
return 0
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
release_lock() {
|
|
745
|
-
rmdir "$LOCK_DIR" 2>/dev/null || true
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
rotate_file() {
|
|
749
|
-
local file_path="$1"
|
|
750
|
-
local keep_lines="$2"
|
|
751
|
-
if [ ! -f "$file_path" ]; then
|
|
752
|
-
return
|
|
753
|
-
fi
|
|
754
|
-
local line_count
|
|
755
|
-
line_count=$(wc -l < "$file_path" 2>/dev/null | tr -d ' ')
|
|
756
|
-
if [ -z "$line_count" ]; then
|
|
757
|
-
return
|
|
758
|
-
fi
|
|
759
|
-
if [ "$line_count" -gt $((keep_lines * 2)) ]; then
|
|
760
|
-
local tmp_path="\${file_path}.tmp.$$"
|
|
761
|
-
if tail -n "$keep_lines" "$file_path" > "$tmp_path" 2>/dev/null; then
|
|
762
|
-
mv "$tmp_path" "$file_path" 2>/dev/null || rm -f "$tmp_path" 2>/dev/null || true
|
|
763
|
-
fi
|
|
764
|
-
fi
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
sync_run_artifacts() {
|
|
768
|
-
if [ "$PHASE" != "post" ]; then
|
|
769
|
-
return
|
|
770
|
-
fi
|
|
771
|
-
[ -n "$ACTIVE_RUN" ] || return
|
|
772
|
-
if [ "$ACTIVE_RUN" = "none" ]; then
|
|
773
|
-
return
|
|
774
|
-
fi
|
|
775
|
-
|
|
776
|
-
local tool_lower
|
|
777
|
-
tool_lower=$(printf '%s' "$TOOL" | tr '[:upper:]' '[:lower:]')
|
|
778
|
-
case "$tool_lower" in
|
|
779
|
-
write|edit|multiedit|multi_edit|delete|applypatch|runcommand|shell|terminal|execcommand) ;;
|
|
780
|
-
*) return ;;
|
|
781
|
-
esac
|
|
782
|
-
|
|
783
|
-
local active_dir="$ROOT/${RUNTIME_ROOT}/artifacts"
|
|
784
|
-
local run_dir="$ROOT/${RUNTIME_ROOT}/runs/$ACTIVE_RUN/artifacts"
|
|
785
|
-
[ -d "$active_dir" ] || return
|
|
786
|
-
mkdir -p "$run_dir" 2>/dev/null || return
|
|
787
|
-
|
|
788
|
-
for run_file in "$run_dir"/*; do
|
|
789
|
-
[ -e "$run_file" ] || continue
|
|
790
|
-
[ -f "$run_file" ] || continue
|
|
791
|
-
local base_name
|
|
792
|
-
base_name=$(basename "$run_file")
|
|
793
|
-
local active_file="$active_dir/$base_name"
|
|
794
|
-
if [ ! -f "$active_file" ]; then
|
|
795
|
-
rm -f "$run_file" 2>/dev/null || true
|
|
796
|
-
continue
|
|
797
|
-
fi
|
|
798
|
-
if command -v cmp >/dev/null 2>&1 && cmp -s "$active_file" "$run_file" 2>/dev/null; then
|
|
799
|
-
continue
|
|
800
|
-
fi
|
|
801
|
-
cp "$active_file" "$run_file" 2>/dev/null || true
|
|
802
|
-
done
|
|
803
|
-
|
|
804
|
-
for active_file in "$active_dir"/*; do
|
|
805
|
-
[ -e "$active_file" ] || continue
|
|
806
|
-
[ -f "$active_file" ] || continue
|
|
807
|
-
local base_name
|
|
808
|
-
base_name=$(basename "$active_file")
|
|
809
|
-
local run_file="$run_dir/$base_name"
|
|
810
|
-
if [ -f "$run_file" ] && command -v cmp >/dev/null 2>&1 && cmp -s "$active_file" "$run_file" 2>/dev/null; then
|
|
811
|
-
continue
|
|
812
|
-
fi
|
|
813
|
-
cp "$active_file" "$run_file" 2>/dev/null || true
|
|
814
|
-
done
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
# Read stdin (hook JSON)
|
|
818
|
-
INPUT=$(cat 2>/dev/null || echo '{}')
|
|
819
|
-
[ -z "$INPUT" ] && exit 0
|
|
820
|
-
|
|
821
|
-
# Extract fields from hook payload.
|
|
822
|
-
TOOL="unknown"
|
|
823
|
-
PAYLOAD=""
|
|
824
|
-
if command -v jq >/dev/null 2>&1; then
|
|
825
|
-
TOOL=$(echo "$INPUT" | jq -r '.tool_name // .tool // .toolName // .name // .id // .command // .tool.name // .tool.id // .input.tool_name // .input.tool // .input.toolName // .input.name // .input.id // .input.command // .input.tool.name // .input.tool.id // "unknown"' 2>/dev/null || echo "unknown")
|
|
826
|
-
if [ "$PHASE" = "pre" ]; then
|
|
827
|
-
PAYLOAD=$(echo "$INPUT" | jq -r --arg max "$MAX_LEN" '.tool_input // .input // {} | tostring | .[0:($max|tonumber)]' 2>/dev/null || echo "")
|
|
828
|
-
else
|
|
829
|
-
PAYLOAD=$(echo "$INPUT" | jq -r --arg max "$MAX_LEN" '.tool_response // .tool_output // .output // .result_json // "" | tostring | .[0:($max|tonumber)]' 2>/dev/null || echo "")
|
|
830
|
-
fi
|
|
831
|
-
else
|
|
832
|
-
TOOL=$(printf '%s' "$INPUT" | sed -n -E 's/.*"tool_name"[[:space:]]*:[[:space:]]*"([^"]+)".*/\\1/p' | head -1)
|
|
833
|
-
if [ -z "$TOOL" ]; then
|
|
834
|
-
TOOL=$(printf '%s' "$INPUT" | sed -n -E 's/.*"tool"[[:space:]]*:[[:space:]]*"([^"]+)".*/\\1/p' | head -1)
|
|
835
|
-
fi
|
|
836
|
-
[ -n "$TOOL" ] || TOOL="unknown"
|
|
837
|
-
PAYLOAD=$(printf '%s' "$INPUT" | cut -c1-"$MAX_LEN")
|
|
838
|
-
fi
|
|
839
|
-
|
|
840
|
-
TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || echo "")
|
|
841
|
-
STAGE="none"
|
|
842
|
-
ACTIVE_RUN="none"
|
|
843
|
-
if [ -f "$STATE_FILE" ]; then
|
|
844
|
-
if command -v jq >/dev/null 2>&1; then
|
|
845
|
-
STAGE=$(jq -r '.currentStage // "none"' "$STATE_FILE" 2>/dev/null || echo "none")
|
|
846
|
-
ACTIVE_RUN=$(jq -r '.activeRunId // "none"' "$STATE_FILE" 2>/dev/null || echo "none")
|
|
847
|
-
elif command -v python3 >/dev/null 2>&1; then
|
|
848
|
-
STAGE=$(python3 - "$STATE_FILE" <<'PY'
|
|
849
|
-
import json
|
|
850
|
-
import sys
|
|
851
|
-
|
|
852
|
-
stage = "none"
|
|
853
|
-
try:
|
|
854
|
-
with open(sys.argv[1], "r", encoding="utf-8") as fh:
|
|
855
|
-
data = json.load(fh)
|
|
856
|
-
value = data.get("currentStage")
|
|
857
|
-
if isinstance(value, str) and value:
|
|
858
|
-
stage = value
|
|
859
|
-
except Exception:
|
|
860
|
-
pass
|
|
861
|
-
print(stage)
|
|
862
|
-
PY
|
|
863
|
-
)
|
|
864
|
-
ACTIVE_RUN=$(python3 - "$STATE_FILE" <<'PY'
|
|
865
|
-
import json
|
|
866
|
-
import sys
|
|
867
|
-
|
|
868
|
-
run_id = "none"
|
|
869
|
-
try:
|
|
870
|
-
with open(sys.argv[1], "r", encoding="utf-8") as fh:
|
|
871
|
-
data = json.load(fh)
|
|
872
|
-
value = data.get("activeRunId")
|
|
873
|
-
if isinstance(value, str) and value:
|
|
874
|
-
run_id = value
|
|
875
|
-
except Exception:
|
|
876
|
-
pass
|
|
877
|
-
print(run_id)
|
|
878
|
-
PY
|
|
879
|
-
)
|
|
880
|
-
else
|
|
881
|
-
STAGE=$(grep -o '"currentStage"[[:space:]]*:[[:space:]]*"[^"]*"' "$STATE_FILE" 2>/dev/null | head -1 | sed 's/.*"\\([^"]*\\)"$/\\1/' || echo "none")
|
|
882
|
-
ACTIVE_RUN=$(grep -o '"activeRunId"[[:space:]]*:[[:space:]]*"[^"]*"' "$STATE_FILE" 2>/dev/null | head -1 | sed 's/.*"\\([^"]*\\)"$/\\1/' || echo "none")
|
|
883
|
-
fi
|
|
884
|
-
fi
|
|
885
|
-
|
|
886
|
-
# Skip observation of cclaw hooks to avoid recursion
|
|
887
|
-
case "$TOOL" in
|
|
888
|
-
cclaw*|*cclaw-hook*|observe) exit 0 ;;
|
|
889
|
-
esac
|
|
890
|
-
|
|
891
|
-
if [ "$PHASE" = "pre" ]; then
|
|
892
|
-
EVENT="tool_start"
|
|
893
|
-
else
|
|
894
|
-
EVENT="tool_complete"
|
|
895
|
-
fi
|
|
896
|
-
|
|
897
|
-
# Scrub potential secrets (env vars, tokens, keys) — BSD/macOS sed compatible
|
|
898
|
-
PAYLOAD=$(echo "$PAYLOAD" | sed -E 's/[A-Za-z0-9_]*([Kk][Ee][Yy]|[Tt][Oo][Kk][Ee][Nn]|[Ss][Ee][Cc][Rr][Ee][Tt]|[Pp][Aa][Ss][Ss][Ww][Oo][Rr][Dd]|[Cc][Rr][Ee][Dd][Ee][Nn][Tt][Ii][Aa][Ll])[A-Za-z0-9_]*[=:][^ ",}]+/[REDACTED]/g' 2>/dev/null || echo "$PAYLOAD")
|
|
899
|
-
|
|
900
|
-
# Build JSONL lines.
|
|
901
|
-
if command -v jq >/dev/null 2>&1; then
|
|
902
|
-
EVENT_JSON=$(jq -n -c \\
|
|
903
|
-
--arg ts "$TS" \\
|
|
904
|
-
--arg event "$EVENT" \\
|
|
905
|
-
--arg tool "$TOOL" \\
|
|
906
|
-
--arg phase "$PHASE" \\
|
|
907
|
-
--arg stage "$STAGE" \\
|
|
908
|
-
--arg runId "$ACTIVE_RUN" \\
|
|
909
|
-
--arg payload "$PAYLOAD" \\
|
|
910
|
-
'{ts:$ts,event:$event,tool:$tool,phase:$phase,stage:$stage,runId:$runId,data:$payload}' 2>/dev/null || echo "")
|
|
911
|
-
ACTIVITY_JSON=$(jq -n -c \\
|
|
912
|
-
--arg ts "$TS" \\
|
|
913
|
-
--arg event "$EVENT" \\
|
|
914
|
-
--arg tool "$TOOL" \\
|
|
915
|
-
--arg phase "$PHASE" \\
|
|
916
|
-
--arg stage "$STAGE" \\
|
|
917
|
-
--arg runId "$ACTIVE_RUN" \\
|
|
918
|
-
--arg schemaVersion "1" \\
|
|
919
|
-
'{ts:$ts,event:$event,tool:$tool,phase:$phase,stage:$stage,runId:$runId,schemaVersion:($schemaVersion|tonumber)}' 2>/dev/null || echo "")
|
|
920
|
-
else
|
|
921
|
-
EVENT_JSON=$(printf '{"ts":"%s","event":"%s","tool":"%s","phase":"%s","stage":"%s","runId":"%s","data":"%s"}' \\
|
|
922
|
-
"$(escape_json "$TS")" \\
|
|
923
|
-
"$(escape_json "$EVENT")" \\
|
|
924
|
-
"$(escape_json "$TOOL")" \\
|
|
925
|
-
"$(escape_json "$PHASE")" \\
|
|
926
|
-
"$(escape_json "$STAGE")" \\
|
|
927
|
-
"$(escape_json "$ACTIVE_RUN")" \\
|
|
928
|
-
"$(escape_json "$PAYLOAD")")
|
|
929
|
-
ACTIVITY_JSON=$(printf '{"ts":"%s","event":"%s","tool":"%s","phase":"%s","stage":"%s","runId":"%s","schemaVersion":1}' \\
|
|
930
|
-
"$(escape_json "$TS")" \\
|
|
931
|
-
"$(escape_json "$EVENT")" \\
|
|
932
|
-
"$(escape_json "$TOOL")" \\
|
|
933
|
-
"$(escape_json "$PHASE")" \\
|
|
934
|
-
"$(escape_json "$STAGE")" \\
|
|
935
|
-
"$(escape_json "$ACTIVE_RUN")")
|
|
936
|
-
fi
|
|
937
|
-
|
|
938
|
-
if acquire_lock; then
|
|
939
|
-
trap release_lock EXIT INT TERM
|
|
940
|
-
[ -n "$EVENT_JSON" ] && printf '%s\\n' "$EVENT_JSON" >> "$OBS_FILE" 2>/dev/null
|
|
941
|
-
[ -n "$ACTIVITY_JSON" ] && printf '%s\\n' "$ACTIVITY_JSON" >> "$ACTIVITY_FILE" 2>/dev/null
|
|
942
|
-
rotate_file "$OBS_FILE" 4000
|
|
943
|
-
rotate_file "$ACTIVITY_FILE" 3000
|
|
944
|
-
release_lock
|
|
945
|
-
trap - EXIT INT TERM
|
|
946
|
-
fi
|
|
947
|
-
|
|
948
|
-
sync_run_artifacts
|
|
949
|
-
|
|
950
696
|
exit 0
|
|
951
697
|
`;
|
|
952
698
|
}
|