@cyanautomation/kaseki-agent 1.17.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
 
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
@@ -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
@@ -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.17.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",