@cyanautomation/kaseki-agent 1.16.0 → 1.18.0

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 CHANGED
@@ -1287,6 +1287,7 @@ API controllers may send either the direct fields (`changedFilesAllowlist`, `val
1287
1287
  | `KASEKI_REPO_MEMORY_MODE` | `off` | Opt-in repository prompt memory: `off` disables it; `summary` appends a compact prior-context summary when fresh |
1288
1288
  | `KASEKI_REPO_MEMORY_TTL_DAYS` | `30` | Maximum age for a repository memory summary before it is ignored |
1289
1289
  | `KASEKI_REPO_MEMORY_MAX_BYTES` | `8000` | Maximum bytes to read/write for the repository memory prompt section |
1290
+ | `KASEKI_REPO_MEMORY_ROOT` | `/cache/repo-memory` | Directory root for repository memory summaries |
1290
1291
 
1291
1292
  ### Docker and Images
1292
1293
 
@@ -1415,7 +1416,7 @@ Set `KASEKI_GIT_CACHE_MODE=off` to disable Git mirror caching. Clone duration pl
1415
1416
 
1416
1417
  ### Repository Memory Cache
1417
1418
 
1418
- Repository memory is disabled by default. Set `KASEKI_REPO_MEMORY_MODE=summary` to opt in to a compact prompt-context cache for the target repository and ref. Kaseki stores this summary at `/cache/repo-memory/<repo-key>/summary.md`, where `<repo-key>` is derived from the repository URL and default ref. Before invoking the agent, Kaseki appends a clearly labeled “Prior repository context” section only when the summary exists, is within `KASEKI_REPO_MEMORY_TTL_DAYS`, and is no larger than `KASEKI_REPO_MEMORY_MAX_BYTES`.
1419
+ Repository memory is disabled by default. Set `KASEKI_REPO_MEMORY_MODE=summary` to opt in to a compact prompt-context cache for the target repository and ref. Kaseki stores this summary at `${KASEKI_REPO_MEMORY_ROOT}/<repo-key>/summary.md`, where `KASEKI_REPO_MEMORY_ROOT` defaults to `/cache/repo-memory` and `<repo-key>` is derived from the repository URL and default ref. Before invoking the agent, Kaseki appends a clearly labeled “Prior repository context” section only when the summary exists, is within `KASEKI_REPO_MEMORY_TTL_DAYS`, and is no larger than `KASEKI_REPO_MEMORY_MAX_BYTES`.
1419
1420
 
1420
1421
  After a successful run, or an inspect-mode run where the agent completed and the secret scan passed, Kaseki rewrites the summary from bounded, sanitized artifacts: `result-summary.md`, `analysis.md`, `changed-files.txt`, and validation timing/status outcomes. The summary records the repo URL, default ref, commit SHA, and timestamp so stale context is visible to the next agent. Kaseki does not blindly persist raw logs or user prompts, and lines resembling secrets, credentials, API keys, tokens, or prompt text are filtered out before writing memory.
1421
1422
 
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Validation Output Filter
3
+ *
4
+ * Filters validation command output in real-time to reduce noise in Docker logs
5
+ * while preserving full output in stored log files.
6
+ *
7
+ * Filters OUT verbose lines while preserving:
8
+ * - Error and warning lines (never filtered)
9
+ * - Test result indicators (✓, ✗, PASS, FAIL, passed, failed, etc.)
10
+ * - Command boundaries (first and last lines)
11
+ *
12
+ * Usage:
13
+ * some_command 2>&1 | node validation-output-filter.js | tee -a logfile.log
14
+ *
15
+ * Exit code: Always 0 (this filter does not affect command success/failure)
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=validation-output-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-output-filter.d.ts","sourceRoot":"","sources":["../src/validation-output-filter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Validation Output Filter
3
+ *
4
+ * Filters validation command output in real-time to reduce noise in Docker logs
5
+ * while preserving full output in stored log files.
6
+ *
7
+ * Filters OUT verbose lines while preserving:
8
+ * - Error and warning lines (never filtered)
9
+ * - Test result indicators (✓, ✗, PASS, FAIL, passed, failed, etc.)
10
+ * - Command boundaries (first and last lines)
11
+ *
12
+ * Usage:
13
+ * some_command 2>&1 | node validation-output-filter.js | tee -a logfile.log
14
+ *
15
+ * Exit code: Always 0 (this filter does not affect command success/failure)
16
+ */
17
+ import { createInterface } from 'readline';
18
+ const state = {
19
+ inCommand: false,
20
+ commandNumber: 0,
21
+ firstLineOfCommand: null,
22
+ linesSinceCommandStart: 0,
23
+ };
24
+ /**
25
+ * Patterns that always pass through (never filtered)
26
+ */
27
+ const ALWAYS_SHOW_PATTERNS = [
28
+ /ERROR/i,
29
+ /WARN/i, // Shows real warnings (compiler, linter, etc)
30
+ /FATAL/i,
31
+ /CRITICAL/i,
32
+ /Exception/,
33
+ /at\s+\(/, // Stack traces
34
+ /^\s+at\s+/,
35
+ /failed/i,
36
+ /failure/i,
37
+ ];
38
+ /**
39
+ * Patterns that should be filtered out (verbose/noisy output)
40
+ */
41
+ const FILTER_OUT_PATTERNS = [
42
+ /^npm\s+(notice|warn)/i, // npm notice and warn messages (framework metadata)
43
+ /^npm\s+ERR!/i, // npm error prefixed lines (actual errors shown differently)
44
+ /welcome to npm/i,
45
+ /^\s*\[[\s█▓▒░]*\].*%?\s*(complete|done)/i, // Progress bars
46
+ /\d+%\s+complete/i, // Percentage progress indicators
47
+ ];
48
+ /**
49
+ * Patterns that indicate test results or completion
50
+ */
51
+ const KEY_MILESTONE_PATTERNS = [
52
+ /\bPASS/i,
53
+ /\bFAIL/i,
54
+ /\bOK\b/i,
55
+ /\bDONE\b/i,
56
+ /✓/,
57
+ /✗/,
58
+ /passed/i,
59
+ /failed/i,
60
+ /completed/i,
61
+ /finished/i,
62
+ /complete/i, // "Bundle complete", "Build complete", etc.
63
+ /\d+\s+tests?.*passed/i,
64
+ /\d+\s+tests?.*failed/i,
65
+ /\d+\s+error/i,
66
+ /\d+\s+warning/i,
67
+ /all\s+tests?\s+passed/i,
68
+ /test\s+suite.*passed/i,
69
+ /test\s+suite.*failed/i,
70
+ /\bsuccess\b/i,
71
+ /build.*success/i,
72
+ /build.*success/i,
73
+ /\d+.*tests?\s+(passed|failed)/i,
74
+ ];
75
+ /**
76
+ * Patterns that indicate command boundaries (start/end)
77
+ */
78
+ const COMMAND_BOUNDARY_PATTERNS = [
79
+ /^==> /, // Command start
80
+ /^exit_code=/, // Command end
81
+ ];
82
+ /**
83
+ * Check if a line should always be shown (error/warning)
84
+ */
85
+ function shouldAlwaysShow(line) {
86
+ return ALWAYS_SHOW_PATTERNS.some((pattern) => pattern.test(line));
87
+ }
88
+ /**
89
+ * Check if a line should be filtered out (verbose/noisy)
90
+ */
91
+ function shouldFilterOut(line) {
92
+ return FILTER_OUT_PATTERNS.some((pattern) => pattern.test(line));
93
+ }
94
+ /**
95
+ * Check if a line is a key milestone (test result indicator)
96
+ */
97
+ function isKeyMilestone(line) {
98
+ return KEY_MILESTONE_PATTERNS.some((pattern) => pattern.test(line));
99
+ }
100
+ /**
101
+ * Check if a line is a command boundary
102
+ */
103
+ function isCommandBoundary(line) {
104
+ return COMMAND_BOUNDARY_PATTERNS.some((pattern) => pattern.test(line));
105
+ }
106
+ /**
107
+ * Determine if a line should be shown in real-time output
108
+ */
109
+ function shouldShow(line) {
110
+ // Filter out explicitly noisy patterns first
111
+ if (shouldFilterOut(line)) {
112
+ return false;
113
+ }
114
+ // Always show errors and warnings
115
+ if (shouldAlwaysShow(line)) {
116
+ return true;
117
+ }
118
+ // Always show command boundaries
119
+ if (isCommandBoundary(line)) {
120
+ return true;
121
+ }
122
+ // Always show key milestones (test results)
123
+ if (isKeyMilestone(line)) {
124
+ return true;
125
+ }
126
+ // Filter everything else
127
+ return false;
128
+ }
129
+ /**
130
+ * Process a line of input
131
+ */
132
+ function processLine(line) {
133
+ // Detect command start
134
+ if (line.match(/^==> /)) {
135
+ state.inCommand = true;
136
+ state.commandNumber++;
137
+ state.firstLineOfCommand = line;
138
+ state.linesSinceCommandStart = 0;
139
+ output(line); // Always show command start
140
+ return;
141
+ }
142
+ // Detect command end
143
+ if (line.match(/^exit_code=/)) {
144
+ output(line); // Always show exit code
145
+ state.inCommand = false;
146
+ state.firstLineOfCommand = null;
147
+ state.linesSinceCommandStart = 0;
148
+ return;
149
+ }
150
+ // If not in a command, show the line anyway (e.g., preamble, separators)
151
+ if (!state.inCommand) {
152
+ output(line);
153
+ return;
154
+ }
155
+ // In a command: decide whether to show this line based on filter criteria
156
+ state.linesSinceCommandStart++;
157
+ // Show only lines that match filter criteria (errors, milestones, boundaries)
158
+ if (shouldShow(line)) {
159
+ output(line);
160
+ }
161
+ }
162
+ /**
163
+ * Output a line to stdout
164
+ */
165
+ function output(line) {
166
+ console.log(line);
167
+ }
168
+ /**
169
+ * Main: read from stdin and process
170
+ */
171
+ const rl = createInterface({
172
+ input: process.stdin,
173
+ output: process.stdout,
174
+ terminal: false,
175
+ });
176
+ rl.on('line', (line) => {
177
+ processLine(line);
178
+ });
179
+ rl.on('close', () => {
180
+ process.exit(0);
181
+ });
182
+ // Handle errors gracefully
183
+ process.on('error', (err) => {
184
+ console.error(`[validation-output-filter] Error: ${err.message}`);
185
+ process.exit(1);
186
+ });
187
+ //# sourceMappingURL=validation-output-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-output-filter.js","sourceRoot":"","sources":["../src/validation-output-filter.ts"],"names":[],"mappings":"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"}
package/kaseki-agent.sh CHANGED
@@ -14,6 +14,7 @@ KASEKI_VALIDATION_COMMANDS="${KASEKI_VALIDATION_COMMANDS-npm run check;npm run t
14
14
  KASEKI_SKIP_MISSING_NPM_SCRIPTS="${KASEKI_SKIP_MISSING_NPM_SCRIPTS:-1}"
15
15
  KASEKI_DEBUG_RAW_EVENTS="${KASEKI_DEBUG_RAW_EVENTS:-0}"
16
16
  KASEKI_STREAM_PROGRESS="${KASEKI_STREAM_PROGRESS:-1}"
17
+ KASEKI_RESULTS_DIR="${KASEKI_RESULTS_DIR:-/results}"
17
18
  KASEKI_VALIDATE_AFTER_AGENT_FAILURE="${KASEKI_VALIDATE_AFTER_AGENT_FAILURE:-0}"
18
19
  KASEKI_TASK_MODE="${KASEKI_TASK_MODE:-patch}"
19
20
  KASEKI_ALLOW_EMPTY_DIFF="${KASEKI_ALLOW_EMPTY_DIFF:-0}"
@@ -23,6 +24,7 @@ KASEKI_MAX_DIFF_BYTES="${KASEKI_MAX_DIFF_BYTES:-200000}"
23
24
  KASEKI_REPO_MEMORY_MODE="${KASEKI_REPO_MEMORY_MODE:-off}"
24
25
  KASEKI_REPO_MEMORY_TTL_DAYS="${KASEKI_REPO_MEMORY_TTL_DAYS:-30}"
25
26
  KASEKI_REPO_MEMORY_MAX_BYTES="${KASEKI_REPO_MEMORY_MAX_BYTES:-8000}"
27
+ KASEKI_REPO_MEMORY_ROOT="${KASEKI_REPO_MEMORY_ROOT:-/cache/repo-memory}"
26
28
  TASK_PROMPT="${TASK_PROMPT:-Make normalizeRole treat a non-string Name fallback safely when FriendlyName is empty or missing. It should fall back to \"Unnamed Role\" instead of preserving arbitrary truthy non-string values. Add or update exactly one compact table-driven Vitest case in tests/parser.validation.ts, with a neutral static test title and no per-case assertion messages or explanatory comments. Do not add broad repeated test blocks. Do not print, inspect, or expose environment variables, secrets, credentials, or API keys. Keep changes limited to the source and test files needed for this fix.}"
27
29
  KASEKI_AGENT_GUARDRAILS="${KASEKI_AGENT_GUARDRAILS:-1}"
28
30
  KASEKI_RESTORE_DISALLOWED_CHANGES="${KASEKI_RESTORE_DISALLOWED_CHANGES:-1}"
@@ -1171,7 +1173,7 @@ init_repo_memory_paths() {
1171
1173
  return 0
1172
1174
  fi
1173
1175
  REPO_MEMORY_KEY="$(compute_repo_memory_key)"
1174
- REPO_MEMORY_DIR="/cache/repo-memory/$REPO_MEMORY_KEY"
1176
+ REPO_MEMORY_DIR="$KASEKI_REPO_MEMORY_ROOT/$REPO_MEMORY_KEY"
1175
1177
  REPO_MEMORY_FILE="$REPO_MEMORY_DIR/summary.md"
1176
1178
  REPO_MEMORY_STATUS="enabled"
1177
1179
  }
@@ -1222,10 +1224,10 @@ write_repo_memory_summary() {
1222
1224
  local updated_at
1223
1225
  REPO_MEMORY_COMMIT_SHA="$(git -C /workspace/repo rev-parse HEAD 2>/dev/null || printf 'unknown')"
1224
1226
  updated_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
1225
- node - "$KASEKI_REPO_MEMORY_MAX_BYTES" "$REPO_MEMORY_FILE" "$REPO_URL" "$GIT_REF" "$REPO_MEMORY_COMMIT_SHA" "$updated_at" "$KASEKI_TASK_MODE" "$STATUS" "$PI_EXIT" "$VALIDATION_EXIT" "$QUALITY_EXIT" "$SECRET_SCAN_EXIT" <<'NODE' || {
1227
+ node - "$KASEKI_REPO_MEMORY_MAX_BYTES" "$REPO_MEMORY_FILE" "$KASEKI_RESULTS_DIR" "$REPO_URL" "$GIT_REF" "$REPO_MEMORY_COMMIT_SHA" "$updated_at" "$KASEKI_TASK_MODE" "$STATUS" "$PI_EXIT" "$VALIDATION_EXIT" "$QUALITY_EXIT" "$SECRET_SCAN_EXIT" <<'NODE' || {
1226
1228
  const fs = require('fs');
1227
1229
  const path = require('path');
1228
- const [maxBytesArg, outputFile, repoUrl, gitRef, commitSha, timestamp, taskMode, status, piExit, validationExit, qualityExit, secretScanExit] = process.argv.slice(2);
1230
+ const [maxBytesArg, outputFile, resultsDir, repoUrl, gitRef, commitSha, timestamp, taskMode, status, piExit, validationExit, qualityExit, secretScanExit] = process.argv.slice(2);
1229
1231
  const maxBytes = Math.max(1024, Number(maxBytesArg) || 8000);
1230
1232
 
1231
1233
  function readFile(file, maxChars = 12000) {
@@ -1255,7 +1257,7 @@ function compactLines(text, limit = 16) {
1255
1257
  }
1256
1258
 
1257
1259
  function changedFiles() {
1258
- return sanitize(readFile('/results/changed-files.txt', 4000))
1260
+ return sanitize(readFile(path.join(resultsDir, 'changed-files.txt'), 4000))
1259
1261
  .split(/\r?\n/)
1260
1262
  .map((line) => line.trim())
1261
1263
  .filter(Boolean)
@@ -1263,7 +1265,7 @@ function changedFiles() {
1263
1265
  }
1264
1266
 
1265
1267
  function validationOutcomes() {
1266
- const rows = sanitize(readFile('/results/validation-timings.tsv', 8000))
1268
+ const rows = sanitize(readFile(path.join(resultsDir, 'validation-timings.tsv'), 8000))
1267
1269
  .split(/\r?\n/)
1268
1270
  .map((line) => line.split('\t'))
1269
1271
  .filter((parts) => parts.length >= 2 && parts[0]);
@@ -1271,8 +1273,8 @@ function validationOutcomes() {
1271
1273
  return rows.slice(0, 20).map(([command, exitCode, duration]) => `${command}: exit ${exitCode}${duration ? `, ${duration}s` : ''}`);
1272
1274
  }
1273
1275
 
1274
- const resultLines = compactLines(readFile('/results/result-summary.md'));
1275
- const analysisLines = compactLines(readFile('/results/analysis.md'), 10);
1276
+ const resultLines = compactLines(readFile(path.join(resultsDir, 'result-summary.md')));
1277
+ const analysisLines = compactLines(readFile(path.join(resultsDir, 'analysis.md')), 10);
1276
1278
  const files = changedFiles();
1277
1279
  const validations = validationOutcomes();
1278
1280
 
@@ -2032,7 +2034,7 @@ else
2032
2034
  unset agent_prompt
2033
2035
  PI_DURATION_SECONDS=$(($(date +%s) - PI_START_EPOCH))
2034
2036
  unset OPENROUTER_API_KEY openrouter_api_key openrouter_api_key_source
2035
- set -e
2037
+ set +e
2036
2038
  record_stage_timing "pi coding agent" "$PI_EXIT" "$PI_DURATION_SECONDS" "timeout_seconds=$KASEKI_AGENT_TIMEOUT_SECONDS"
2037
2039
 
2038
2040
  if [ "$KASEKI_DEBUG_RAW_EVENTS" = "1" ]; then
@@ -2042,7 +2044,7 @@ else
2042
2044
  PI_EXTRACTION_DEPS_OK=1
2043
2045
  missing_executables=()
2044
2046
  missing_helpers=()
2045
- for required_exec in kaseki-pi-event-filter kaseki-pi-progress-stream; do
2047
+ for required_exec in kaseki-pi-event-filter kaseki-pi-progress-stream validation-output-filter; do
2046
2048
  if ! command -v "$required_exec" >/dev/null 2>&1; then
2047
2049
  missing_executables+=("$required_exec")
2048
2050
  fi
@@ -2074,7 +2076,7 @@ else
2074
2076
  set +e
2075
2077
  kaseki-pi-event-filter "$RAW_EVENTS" /results/pi-events.jsonl /results/pi-summary.json
2076
2078
  FILTER_EXIT=$?
2077
- set -e
2079
+ set +e
2078
2080
  fi
2079
2081
  if [ "$FILTER_EXIT" -ne 0 ]; then
2080
2082
  printf 'pi-event-filter failed with exit %s; raw events preserved as fallback artifact\n' "$FILTER_EXIT" | tee -a /results/quality.log
@@ -2263,7 +2265,7 @@ else
2263
2265
  command_exit=$?
2264
2266
  printf 'exit_code=%s\n' "$command_exit"
2265
2267
  exit "$command_exit"
2266
- } 2>&1 | tee -a /results/validation.log
2268
+ } 2>&1 | tee -a /results/validation.log | validation-output-filter
2267
2269
  command_exit="${PIPESTATUS[0]}"
2268
2270
  validation_end="$(date +%s)"
2269
2271
  duration=$((validation_end - validation_start))
@@ -2298,7 +2300,7 @@ else
2298
2300
  if [ -n "$VALIDATION_FAILED_COMMAND_DETAIL" ]; then
2299
2301
  printf 'Validation failed: %s\n' "$VALIDATION_FAILED_COMMAND_DETAIL" | tee -a /results/validation.log
2300
2302
  fi
2301
- set -e
2303
+ set +e
2302
2304
  fi
2303
2305
  record_stage_timing "validation" "$VALIDATION_EXIT" "$(($(date +%s) - stage_start))" ""
2304
2306
  fi
@@ -2342,12 +2344,25 @@ emit_progress "secret scan" "finished with exit $SECRET_SCAN_EXIT"
2342
2344
 
2343
2345
  build_github_skip_reasons() {
2344
2346
  GITHUB_SKIP_REASONS=()
2345
- [ "$GITHUB_APP_ENABLED" != "1" ] && GITHUB_SKIP_REASONS+=("github_app_disabled")
2346
- [ "$PI_EXIT" -ne 0 ] && GITHUB_SKIP_REASONS+=("agent_failed")
2347
- [ "$VALIDATION_EXIT" -ne 0 ] && GITHUB_SKIP_REASONS+=("validation_failed")
2348
- [ "$QUALITY_EXIT" -ne 0 ] && GITHUB_SKIP_REASONS+=("quality_failed")
2349
- [ "$SECRET_SCAN_EXIT" -ne 0 ] && GITHUB_SKIP_REASONS+=("secret_scan_failed")
2350
- [ "$DIFF_NONEMPTY" != "true" ] && GITHUB_SKIP_REASONS+=("empty_diff")
2347
+ if [ "$GITHUB_APP_ENABLED" != "1" ]; then
2348
+ GITHUB_SKIP_REASONS+=("github_app_disabled")
2349
+ fi
2350
+ if [ "$PI_EXIT" -ne 0 ]; then
2351
+ GITHUB_SKIP_REASONS+=("agent_failed")
2352
+ fi
2353
+ if [ "$VALIDATION_EXIT" -ne 0 ]; then
2354
+ GITHUB_SKIP_REASONS+=("validation_failed")
2355
+ fi
2356
+ if [ "$QUALITY_EXIT" -ne 0 ]; then
2357
+ GITHUB_SKIP_REASONS+=("quality_failed")
2358
+ fi
2359
+ if [ "$SECRET_SCAN_EXIT" -ne 0 ]; then
2360
+ GITHUB_SKIP_REASONS+=("secret_scan_failed")
2361
+ fi
2362
+ if [ "$DIFF_NONEMPTY" != "true" ]; then
2363
+ GITHUB_SKIP_REASONS+=("empty_diff")
2364
+ fi
2365
+ return 0
2351
2366
  }
2352
2367
 
2353
2368
  printf '\n==> github operations\n'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyanautomation/kaseki-agent",
3
- "version": "1.16.0",
3
+ "version": "1.18.0",
4
4
  "description": "Ephemeral coding-agent runner: orchestrates Pi CLI via Docker for automated code modifications with validation",
5
5
  "type": "module",
6
6
  "license": "MIT",