cognitive-core 0.2.1 → 0.2.2
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/atlas.d.ts +10 -0
- package/dist/atlas.d.ts.map +1 -1
- package/dist/atlas.js +65 -0
- package/dist/atlas.js.map +1 -1
- package/dist/learning/pipeline.d.ts +4 -31
- package/dist/learning/pipeline.d.ts.map +1 -1
- package/dist/learning/pipeline.js +12 -64
- package/dist/learning/pipeline.js.map +1 -1
- package/dist/memory/curated-loader.d.ts +21 -4
- package/dist/memory/curated-loader.d.ts.map +1 -1
- package/dist/memory/curated-loader.js +53 -16
- package/dist/memory/curated-loader.js.map +1 -1
- package/dist/memory/index.d.ts +2 -1
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +3 -1
- package/dist/memory/index.js.map +1 -1
- package/dist/memory/playbook.d.ts +6 -0
- package/dist/memory/playbook.d.ts.map +1 -1
- package/dist/memory/playbook.js +15 -0
- package/dist/memory/playbook.js.map +1 -1
- package/dist/memory/source-resolver.d.ts +120 -0
- package/dist/memory/source-resolver.d.ts.map +1 -0
- package/dist/memory/source-resolver.js +300 -0
- package/dist/memory/source-resolver.js.map +1 -0
- package/dist/types/config.d.ts +141 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +40 -0
- package/dist/types/config.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/workspace/types.d.ts +12 -54
- package/dist/workspace/types.d.ts.map +1 -1
- package/dist/workspace/types.js.map +1 -1
- package/package.json +2 -2
- package/playbooks/compound-engineering/adversarial-review.json +51 -0
- package/playbooks/compound-engineering/agent-native-architecture.json +59 -0
- package/playbooks/compound-engineering/agent-native-review.json +54 -0
- package/playbooks/compound-engineering/api-contract-review.json +52 -0
- package/playbooks/compound-engineering/brainstorm-requirements.json +55 -0
- package/playbooks/compound-engineering/bug-reproduction.json +62 -0
- package/playbooks/compound-engineering/confidence-calibration.json +49 -0
- package/playbooks/compound-engineering/correctness-review.json +49 -0
- package/playbooks/compound-engineering/data-migration-safety.json +59 -0
- package/playbooks/compound-engineering/deployment-verification.json +63 -0
- package/playbooks/compound-engineering/error-recovery-patterns.json +53 -0
- package/playbooks/compound-engineering/implementation-planning.json +64 -0
- package/playbooks/compound-engineering/issue-pattern-analysis.json +53 -0
- package/playbooks/compound-engineering/knowledge-compounding.json +63 -0
- package/playbooks/compound-engineering/learnings-research.json +54 -0
- package/playbooks/compound-engineering/maintainability-review.json +49 -0
- package/playbooks/compound-engineering/performance-review.json +54 -0
- package/playbooks/compound-engineering/plan-adversarial-review.json +56 -0
- package/playbooks/compound-engineering/plan-feasibility-review.json +56 -0
- package/playbooks/compound-engineering/project-standards-review.json +52 -0
- package/playbooks/compound-engineering/reliability-review.json +53 -0
- package/playbooks/compound-engineering/review-orchestration.json +64 -0
- package/playbooks/compound-engineering/security-review.json +54 -0
- package/playbooks/compound-engineering/systematic-execution.json +64 -0
- package/playbooks/compound-engineering/testing-review.json +50 -0
- package/src/atlas.ts +96 -0
- package/src/memory/curated-loader.ts +69 -16
- package/src/memory/index.ts +16 -0
- package/src/memory/playbook.ts +19 -0
- package/src/memory/source-resolver.ts +422 -0
- package/src/types/config.ts +46 -0
- package/src/types/index.ts +4 -0
- package/src/workspace/types.ts +22 -78
- package/tests/integration/curated-sources-e2e.test.ts +502 -0
- package/tests/memory/compound-engineering-seed.test.ts +338 -0
- package/tests/memory/curated-loader-extended.test.ts +225 -0
- package/tests/memory/playbook-quality-validation.test.ts +430 -0
- package/tests/memory/source-resolver.test.ts +700 -0
- package/.claude/settings.local.json +0 -11
- package/dist/learning/llm-extractor.d.ts +0 -88
- package/dist/learning/llm-extractor.d.ts.map +0 -1
- package/dist/learning/llm-extractor.js +0 -372
- package/dist/learning/llm-extractor.js.map +0 -1
- package/dist/learning/loop-coordinator.d.ts +0 -61
- package/dist/learning/loop-coordinator.d.ts.map +0 -1
- package/dist/learning/loop-coordinator.js +0 -96
- package/dist/learning/loop-coordinator.js.map +0 -1
- package/references/agent-workspace/CLAUDE.md +0 -74
- package/references/agent-workspace/README.md +0 -587
- package/references/agent-workspace/media/banner.png +0 -0
- package/references/agent-workspace/package-lock.json +0 -2061
- package/references/agent-workspace/package.json +0 -54
- package/references/agent-workspace/src/handle.ts +0 -122
- package/references/agent-workspace/src/index.ts +0 -32
- package/references/agent-workspace/src/manager.ts +0 -102
- package/references/agent-workspace/src/readers/json.ts +0 -71
- package/references/agent-workspace/src/readers/markdown.ts +0 -37
- package/references/agent-workspace/src/readers/raw.ts +0 -27
- package/references/agent-workspace/src/types.ts +0 -68
- package/references/agent-workspace/src/validation.ts +0 -93
- package/references/agent-workspace/src/writers/json.ts +0 -17
- package/references/agent-workspace/src/writers/markdown.ts +0 -27
- package/references/agent-workspace/src/writers/raw.ts +0 -22
- package/references/agent-workspace/tests/errors.test.ts +0 -652
- package/references/agent-workspace/tests/handle.test.ts +0 -144
- package/references/agent-workspace/tests/manager.test.ts +0 -124
- package/references/agent-workspace/tests/readers.test.ts +0 -205
- package/references/agent-workspace/tests/validation.test.ts +0 -196
- package/references/agent-workspace/tests/writers.test.ts +0 -108
- package/references/agent-workspace/tsconfig.json +0 -20
- package/references/agent-workspace/tsup.config.ts +0 -9
- package/references/minimem/.claude/settings.json +0 -7
- package/references/minimem/.sudocode/issues.jsonl +0 -18
- package/references/minimem/.sudocode/specs.jsonl +0 -1
- package/references/minimem/CLAUDE.md +0 -310
- package/references/minimem/README.md +0 -556
- package/references/minimem/claude-plugin/.claude-plugin/plugin.json +0 -10
- package/references/minimem/claude-plugin/.mcp.json +0 -7
- package/references/minimem/claude-plugin/README.md +0 -158
- package/references/minimem/claude-plugin/commands/recall.md +0 -47
- package/references/minimem/claude-plugin/commands/remember.md +0 -41
- package/references/minimem/claude-plugin/hooks/__tests__/hooks.test.ts +0 -272
- package/references/minimem/claude-plugin/hooks/hooks.json +0 -27
- package/references/minimem/claude-plugin/hooks/session-end.sh +0 -86
- package/references/minimem/claude-plugin/hooks/session-start.sh +0 -85
- package/references/minimem/claude-plugin/skills/memory/SKILL.md +0 -108
- package/references/minimem/package-lock.json +0 -5373
- package/references/minimem/package.json +0 -60
- package/references/minimem/scripts/postbuild.js +0 -35
- package/references/minimem/src/__tests__/edge-cases.test.ts +0 -371
- package/references/minimem/src/__tests__/errors.test.ts +0 -265
- package/references/minimem/src/__tests__/helpers.ts +0 -199
- package/references/minimem/src/__tests__/internal.test.ts +0 -407
- package/references/minimem/src/__tests__/knowledge.test.ts +0 -287
- package/references/minimem/src/__tests__/minimem.integration.test.ts +0 -1127
- package/references/minimem/src/__tests__/session.test.ts +0 -190
- package/references/minimem/src/cli/__tests__/commands.test.ts +0 -759
- package/references/minimem/src/cli/commands/__tests__/conflicts.test.ts +0 -141
- package/references/minimem/src/cli/commands/append.ts +0 -76
- package/references/minimem/src/cli/commands/config.ts +0 -262
- package/references/minimem/src/cli/commands/conflicts.ts +0 -413
- package/references/minimem/src/cli/commands/daemon.ts +0 -169
- package/references/minimem/src/cli/commands/index.ts +0 -12
- package/references/minimem/src/cli/commands/init.ts +0 -88
- package/references/minimem/src/cli/commands/mcp.ts +0 -177
- package/references/minimem/src/cli/commands/push-pull.ts +0 -213
- package/references/minimem/src/cli/commands/search.ts +0 -158
- package/references/minimem/src/cli/commands/status.ts +0 -84
- package/references/minimem/src/cli/commands/sync-init.ts +0 -290
- package/references/minimem/src/cli/commands/sync.ts +0 -70
- package/references/minimem/src/cli/commands/upsert.ts +0 -197
- package/references/minimem/src/cli/config.ts +0 -584
- package/references/minimem/src/cli/index.ts +0 -264
- package/references/minimem/src/cli/shared.ts +0 -161
- package/references/minimem/src/cli/sync/__tests__/central.test.ts +0 -152
- package/references/minimem/src/cli/sync/__tests__/conflicts.test.ts +0 -209
- package/references/minimem/src/cli/sync/__tests__/daemon.test.ts +0 -118
- package/references/minimem/src/cli/sync/__tests__/detection.test.ts +0 -207
- package/references/minimem/src/cli/sync/__tests__/integration.test.ts +0 -476
- package/references/minimem/src/cli/sync/__tests__/registry.test.ts +0 -363
- package/references/minimem/src/cli/sync/__tests__/state.test.ts +0 -255
- package/references/minimem/src/cli/sync/__tests__/validation.test.ts +0 -193
- package/references/minimem/src/cli/sync/__tests__/watcher.test.ts +0 -178
- package/references/minimem/src/cli/sync/central.ts +0 -292
- package/references/minimem/src/cli/sync/conflicts.ts +0 -204
- package/references/minimem/src/cli/sync/daemon.ts +0 -407
- package/references/minimem/src/cli/sync/detection.ts +0 -138
- package/references/minimem/src/cli/sync/index.ts +0 -107
- package/references/minimem/src/cli/sync/operations.ts +0 -373
- package/references/minimem/src/cli/sync/registry.ts +0 -279
- package/references/minimem/src/cli/sync/state.ts +0 -355
- package/references/minimem/src/cli/sync/validation.ts +0 -206
- package/references/minimem/src/cli/sync/watcher.ts +0 -234
- package/references/minimem/src/cli/version.ts +0 -34
- package/references/minimem/src/core/index.ts +0 -9
- package/references/minimem/src/core/indexer.ts +0 -628
- package/references/minimem/src/core/searcher.ts +0 -221
- package/references/minimem/src/db/schema.ts +0 -183
- package/references/minimem/src/db/sqlite-vec.ts +0 -24
- package/references/minimem/src/embeddings/__tests__/embeddings.test.ts +0 -431
- package/references/minimem/src/embeddings/batch-gemini.ts +0 -392
- package/references/minimem/src/embeddings/batch-openai.ts +0 -409
- package/references/minimem/src/embeddings/embeddings.ts +0 -434
- package/references/minimem/src/index.ts +0 -109
- package/references/minimem/src/internal.ts +0 -299
- package/references/minimem/src/minimem.ts +0 -1276
- package/references/minimem/src/search/__tests__/hybrid.test.ts +0 -247
- package/references/minimem/src/search/graph.ts +0 -234
- package/references/minimem/src/search/hybrid.ts +0 -151
- package/references/minimem/src/search/search.ts +0 -256
- package/references/minimem/src/server/__tests__/mcp.test.ts +0 -341
- package/references/minimem/src/server/__tests__/tools.test.ts +0 -364
- package/references/minimem/src/server/mcp.ts +0 -326
- package/references/minimem/src/server/tools.ts +0 -720
- package/references/minimem/src/session.ts +0 -460
- package/references/minimem/tsconfig.json +0 -19
- package/references/minimem/tsup.config.ts +0 -26
- package/references/minimem/vitest.config.ts +0 -24
- package/references/sessionlog/.husky/pre-commit +0 -1
- package/references/sessionlog/.lintstagedrc.json +0 -4
- package/references/sessionlog/.prettierignore +0 -4
- package/references/sessionlog/.prettierrc.json +0 -11
- package/references/sessionlog/LICENSE +0 -21
- package/references/sessionlog/README.md +0 -453
- package/references/sessionlog/eslint.config.js +0 -58
- package/references/sessionlog/package-lock.json +0 -3672
- package/references/sessionlog/package.json +0 -65
- package/references/sessionlog/src/__tests__/agent-hooks.test.ts +0 -570
- package/references/sessionlog/src/__tests__/agent-registry.test.ts +0 -127
- package/references/sessionlog/src/__tests__/claude-code-hooks.test.ts +0 -225
- package/references/sessionlog/src/__tests__/claude-generator.test.ts +0 -46
- package/references/sessionlog/src/__tests__/commit-msg.test.ts +0 -86
- package/references/sessionlog/src/__tests__/cursor-agent.test.ts +0 -224
- package/references/sessionlog/src/__tests__/e2e-live.test.ts +0 -890
- package/references/sessionlog/src/__tests__/event-log.test.ts +0 -183
- package/references/sessionlog/src/__tests__/flush-sentinel.test.ts +0 -105
- package/references/sessionlog/src/__tests__/gemini-agent.test.ts +0 -375
- package/references/sessionlog/src/__tests__/git-hooks.test.ts +0 -78
- package/references/sessionlog/src/__tests__/hook-managers.test.ts +0 -121
- package/references/sessionlog/src/__tests__/lifecycle-tasks.test.ts +0 -759
- package/references/sessionlog/src/__tests__/opencode-agent.test.ts +0 -338
- package/references/sessionlog/src/__tests__/redaction.test.ts +0 -136
- package/references/sessionlog/src/__tests__/session-repo.test.ts +0 -353
- package/references/sessionlog/src/__tests__/session-store.test.ts +0 -166
- package/references/sessionlog/src/__tests__/setup-ccweb.test.ts +0 -466
- package/references/sessionlog/src/__tests__/skill-live.test.ts +0 -461
- package/references/sessionlog/src/__tests__/summarize.test.ts +0 -348
- package/references/sessionlog/src/__tests__/task-plan-e2e.test.ts +0 -610
- package/references/sessionlog/src/__tests__/task-plan-live.test.ts +0 -632
- package/references/sessionlog/src/__tests__/transcript-timestamp.test.ts +0 -121
- package/references/sessionlog/src/__tests__/types.test.ts +0 -166
- package/references/sessionlog/src/__tests__/utils.test.ts +0 -333
- package/references/sessionlog/src/__tests__/validation.test.ts +0 -103
- package/references/sessionlog/src/__tests__/worktree.test.ts +0 -57
- package/references/sessionlog/src/agent/agents/claude-code.ts +0 -1089
- package/references/sessionlog/src/agent/agents/cursor.ts +0 -361
- package/references/sessionlog/src/agent/agents/gemini-cli.ts +0 -632
- package/references/sessionlog/src/agent/agents/opencode.ts +0 -540
- package/references/sessionlog/src/agent/registry.ts +0 -143
- package/references/sessionlog/src/agent/session-types.ts +0 -113
- package/references/sessionlog/src/agent/types.ts +0 -220
- package/references/sessionlog/src/cli.ts +0 -597
- package/references/sessionlog/src/commands/clean.ts +0 -133
- package/references/sessionlog/src/commands/disable.ts +0 -84
- package/references/sessionlog/src/commands/doctor.ts +0 -145
- package/references/sessionlog/src/commands/enable.ts +0 -202
- package/references/sessionlog/src/commands/explain.ts +0 -261
- package/references/sessionlog/src/commands/reset.ts +0 -105
- package/references/sessionlog/src/commands/resume.ts +0 -180
- package/references/sessionlog/src/commands/rewind.ts +0 -195
- package/references/sessionlog/src/commands/setup-ccweb.ts +0 -275
- package/references/sessionlog/src/commands/status.ts +0 -172
- package/references/sessionlog/src/config.ts +0 -165
- package/references/sessionlog/src/events/event-log.ts +0 -126
- package/references/sessionlog/src/git-operations.ts +0 -558
- package/references/sessionlog/src/hooks/git-hooks.ts +0 -165
- package/references/sessionlog/src/hooks/lifecycle.ts +0 -391
- package/references/sessionlog/src/index.ts +0 -650
- package/references/sessionlog/src/security/redaction.ts +0 -283
- package/references/sessionlog/src/session/state-machine.ts +0 -452
- package/references/sessionlog/src/store/checkpoint-store.ts +0 -509
- package/references/sessionlog/src/store/native-store.ts +0 -173
- package/references/sessionlog/src/store/provider-types.ts +0 -99
- package/references/sessionlog/src/store/session-store.ts +0 -266
- package/references/sessionlog/src/strategy/attribution.ts +0 -296
- package/references/sessionlog/src/strategy/common.ts +0 -207
- package/references/sessionlog/src/strategy/content-overlap.ts +0 -228
- package/references/sessionlog/src/strategy/manual-commit.ts +0 -988
- package/references/sessionlog/src/strategy/types.ts +0 -279
- package/references/sessionlog/src/summarize/claude-generator.ts +0 -115
- package/references/sessionlog/src/summarize/summarize.ts +0 -432
- package/references/sessionlog/src/types.ts +0 -508
- package/references/sessionlog/src/utils/chunk-files.ts +0 -49
- package/references/sessionlog/src/utils/commit-message.ts +0 -65
- package/references/sessionlog/src/utils/detect-agent.ts +0 -36
- package/references/sessionlog/src/utils/hook-managers.ts +0 -125
- package/references/sessionlog/src/utils/ide-tags.ts +0 -32
- package/references/sessionlog/src/utils/paths.ts +0 -79
- package/references/sessionlog/src/utils/preview-rewind.ts +0 -80
- package/references/sessionlog/src/utils/rewind-conflict.ts +0 -121
- package/references/sessionlog/src/utils/shadow-branch.ts +0 -109
- package/references/sessionlog/src/utils/string-utils.ts +0 -46
- package/references/sessionlog/src/utils/todo-extract.ts +0 -188
- package/references/sessionlog/src/utils/trailers.ts +0 -187
- package/references/sessionlog/src/utils/transcript-parse.ts +0 -177
- package/references/sessionlog/src/utils/transcript-timestamp.ts +0 -59
- package/references/sessionlog/src/utils/tree-ops.ts +0 -219
- package/references/sessionlog/src/utils/tty.ts +0 -72
- package/references/sessionlog/src/utils/validation.ts +0 -65
- package/references/sessionlog/src/utils/worktree.ts +0 -58
- package/references/sessionlog/src/wire-types.ts +0 -59
- package/references/sessionlog/templates/setup-env.sh +0 -153
- package/references/sessionlog/tsconfig.json +0 -18
- package/references/sessionlog/vitest.config.ts +0 -12
- package/references/skill-tree/.claude/settings.json +0 -6
- package/references/skill-tree/.sudocode/issues.jsonl +0 -19
- package/references/skill-tree/.sudocode/specs.jsonl +0 -3
- package/references/skill-tree/CLAUDE.md +0 -126
- package/references/skill-tree/README.md +0 -372
- package/references/skill-tree/docs/GAPS_v1.md +0 -221
- package/references/skill-tree/docs/INTEGRATION_PLAN.md +0 -467
- package/references/skill-tree/docs/TODOS.md +0 -91
- package/references/skill-tree/docs/anthropic_skill_guide.md +0 -1364
- package/references/skill-tree/docs/design/federated-skill-trees.md +0 -524
- package/references/skill-tree/docs/design/multi-agent-sync.md +0 -759
- package/references/skill-tree/docs/scraper/BRAINSTORM.md +0 -583
- package/references/skill-tree/docs/scraper/POC_PLAN.md +0 -420
- package/references/skill-tree/docs/scraper/README.md +0 -170
- package/references/skill-tree/examples/basic-usage.ts +0 -164
- package/references/skill-tree/package-lock.json +0 -1852
- package/references/skill-tree/package.json +0 -66
- package/references/skill-tree/scraper/README.md +0 -123
- package/references/skill-tree/scraper/docs/DESIGN.md +0 -683
- package/references/skill-tree/scraper/docs/PLAN.md +0 -336
- package/references/skill-tree/scraper/drizzle.config.ts +0 -10
- package/references/skill-tree/scraper/package-lock.json +0 -6329
- package/references/skill-tree/scraper/package.json +0 -68
- package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-description.md +0 -7
- package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-name.md +0 -7
- package/references/skill-tree/scraper/test/fixtures/minimal-skill/SKILL.md +0 -27
- package/references/skill-tree/scraper/test/fixtures/skill-json/SKILL.json +0 -21
- package/references/skill-tree/scraper/test/fixtures/skill-with-meta/SKILL.md +0 -54
- package/references/skill-tree/scraper/test/fixtures/skill-with-meta/_meta.json +0 -24
- package/references/skill-tree/scraper/test/fixtures/valid-skill/SKILL.md +0 -93
- package/references/skill-tree/scraper/test/fixtures/valid-skill/_meta.json +0 -22
- package/references/skill-tree/scraper/tsup.config.ts +0 -14
- package/references/skill-tree/scraper/vitest.config.ts +0 -17
- package/references/skill-tree/scripts/convert-to-vitest.ts +0 -166
- package/references/skill-tree/skills/skill-writer/SKILL.md +0 -339
- package/references/skill-tree/skills/skill-writer/references/examples.md +0 -326
- package/references/skill-tree/skills/skill-writer/references/patterns.md +0 -210
- package/references/skill-tree/skills/skill-writer/references/quality-checklist.md +0 -123
- package/references/skill-tree/test/run-all.ts +0 -106
- package/references/skill-tree/test/utils.ts +0 -128
- package/references/skill-tree/vitest.config.ts +0 -16
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the event log module (JSONL checkpoint event log).
|
|
3
|
-
*
|
|
4
|
-
* Covers:
|
|
5
|
-
* - appendCheckpointEvent writes valid JSONL
|
|
6
|
-
* - readCheckpointEvents returns events in order
|
|
7
|
-
* - Pruning with maxEvents keeps only the last N
|
|
8
|
-
* - Missing file returns empty array
|
|
9
|
-
* - Exports from the main index
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
13
|
-
import * as fs from 'node:fs';
|
|
14
|
-
import * as path from 'node:path';
|
|
15
|
-
import * as os from 'node:os';
|
|
16
|
-
import {
|
|
17
|
-
appendCheckpointEvent,
|
|
18
|
-
readCheckpointEvents,
|
|
19
|
-
type CheckpointEvent,
|
|
20
|
-
} from '../events/event-log.js';
|
|
21
|
-
import { SESSIONLOG_EVENTS_FILE } from '../types.js';
|
|
22
|
-
|
|
23
|
-
// Also verify re-exports from main index
|
|
24
|
-
import {
|
|
25
|
-
appendCheckpointEvent as indexAppend,
|
|
26
|
-
readCheckpointEvents as indexRead,
|
|
27
|
-
SESSIONLOG_EVENTS_FILE as indexEventsFile,
|
|
28
|
-
} from '../index.js';
|
|
29
|
-
|
|
30
|
-
describe('event-log', () => {
|
|
31
|
-
let tmpDir: string;
|
|
32
|
-
|
|
33
|
-
beforeEach(() => {
|
|
34
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'sessionlog-events-'));
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
afterEach(() => {
|
|
38
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
function makeEvent(id: string, overrides?: Partial<CheckpointEvent>): CheckpointEvent {
|
|
42
|
-
return {
|
|
43
|
-
type: 'checkpoint_committed',
|
|
44
|
-
timestamp: new Date().toISOString(),
|
|
45
|
-
checkpointID: id,
|
|
46
|
-
sessionID: 'sess-1',
|
|
47
|
-
agent: 'Claude Code',
|
|
48
|
-
filesTouched: ['src/app.ts'],
|
|
49
|
-
checkpointsCount: 1,
|
|
50
|
-
...overrides,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function eventsFilePath(): string {
|
|
55
|
-
return path.join(tmpDir, SESSIONLOG_EVENTS_FILE);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
describe('appendCheckpointEvent', () => {
|
|
59
|
-
it('should create the events file and write a JSONL line', async () => {
|
|
60
|
-
const event = makeEvent('cp-001');
|
|
61
|
-
await appendCheckpointEvent(tmpDir, event);
|
|
62
|
-
|
|
63
|
-
const raw = fs.readFileSync(eventsFilePath(), 'utf-8');
|
|
64
|
-
const lines = raw.trim().split('\n');
|
|
65
|
-
expect(lines).toHaveLength(1);
|
|
66
|
-
|
|
67
|
-
const parsed = JSON.parse(lines[0]);
|
|
68
|
-
expect(parsed.type).toBe('checkpoint_committed');
|
|
69
|
-
expect(parsed.checkpointID).toBe('cp-001');
|
|
70
|
-
expect(parsed.agent).toBe('Claude Code');
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('should append multiple events as separate lines', async () => {
|
|
74
|
-
await appendCheckpointEvent(tmpDir, makeEvent('cp-001'));
|
|
75
|
-
await appendCheckpointEvent(tmpDir, makeEvent('cp-002'));
|
|
76
|
-
await appendCheckpointEvent(tmpDir, makeEvent('cp-003'));
|
|
77
|
-
|
|
78
|
-
const raw = fs.readFileSync(eventsFilePath(), 'utf-8');
|
|
79
|
-
const lines = raw.trim().split('\n');
|
|
80
|
-
expect(lines).toHaveLength(3);
|
|
81
|
-
expect(JSON.parse(lines[0]).checkpointID).toBe('cp-001');
|
|
82
|
-
expect(JSON.parse(lines[2]).checkpointID).toBe('cp-003');
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('should include optional fields when present', async () => {
|
|
86
|
-
const event = makeEvent('cp-001', {
|
|
87
|
-
branch: 'feature/auth',
|
|
88
|
-
tokenUsage: {
|
|
89
|
-
inputTokens: 5000,
|
|
90
|
-
outputTokens: 1200,
|
|
91
|
-
cacheCreationTokens: 0,
|
|
92
|
-
cacheReadTokens: 3000,
|
|
93
|
-
apiCallCount: 8,
|
|
94
|
-
},
|
|
95
|
-
});
|
|
96
|
-
await appendCheckpointEvent(tmpDir, event);
|
|
97
|
-
|
|
98
|
-
const events = readCheckpointEvents(tmpDir);
|
|
99
|
-
expect(events[0].branch).toBe('feature/auth');
|
|
100
|
-
expect(events[0].tokenUsage?.inputTokens).toBe(5000);
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
describe('readCheckpointEvents', () => {
|
|
105
|
-
it('should return empty array for missing file', () => {
|
|
106
|
-
const events = readCheckpointEvents(tmpDir);
|
|
107
|
-
expect(events).toEqual([]);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('should return events in chronological order', async () => {
|
|
111
|
-
await appendCheckpointEvent(tmpDir, makeEvent('cp-001'));
|
|
112
|
-
await appendCheckpointEvent(tmpDir, makeEvent('cp-002'));
|
|
113
|
-
|
|
114
|
-
const events = readCheckpointEvents(tmpDir);
|
|
115
|
-
expect(events).toHaveLength(2);
|
|
116
|
-
expect(events[0].checkpointID).toBe('cp-001');
|
|
117
|
-
expect(events[1].checkpointID).toBe('cp-002');
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('should skip malformed lines', async () => {
|
|
121
|
-
// Write a valid line, a bad line, and another valid line
|
|
122
|
-
const filePath = eventsFilePath();
|
|
123
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
124
|
-
fs.writeFileSync(
|
|
125
|
-
filePath,
|
|
126
|
-
JSON.stringify(makeEvent('cp-001')) +
|
|
127
|
-
'\n' +
|
|
128
|
-
'not valid json\n' +
|
|
129
|
-
JSON.stringify(makeEvent('cp-002')) +
|
|
130
|
-
'\n',
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
const events = readCheckpointEvents(tmpDir);
|
|
134
|
-
expect(events).toHaveLength(2);
|
|
135
|
-
expect(events[0].checkpointID).toBe('cp-001');
|
|
136
|
-
expect(events[1].checkpointID).toBe('cp-002');
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
describe('pruning with maxEvents', () => {
|
|
141
|
-
it('should keep only the last N events', async () => {
|
|
142
|
-
for (let i = 1; i <= 5; i++) {
|
|
143
|
-
await appendCheckpointEvent(tmpDir, makeEvent(`cp-${String(i).padStart(3, '0')}`), {
|
|
144
|
-
maxEvents: 3,
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const events = readCheckpointEvents(tmpDir);
|
|
149
|
-
expect(events).toHaveLength(3);
|
|
150
|
-
expect(events[0].checkpointID).toBe('cp-003');
|
|
151
|
-
expect(events[1].checkpointID).toBe('cp-004');
|
|
152
|
-
expect(events[2].checkpointID).toBe('cp-005');
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('should not prune when maxEvents is 0', async () => {
|
|
156
|
-
for (let i = 1; i <= 5; i++) {
|
|
157
|
-
await appendCheckpointEvent(tmpDir, makeEvent(`cp-${String(i).padStart(3, '0')}`), {
|
|
158
|
-
maxEvents: 0,
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const events = readCheckpointEvents(tmpDir);
|
|
163
|
-
expect(events).toHaveLength(5);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it('should not prune when maxEvents is undefined', async () => {
|
|
167
|
-
for (let i = 1; i <= 5; i++) {
|
|
168
|
-
await appendCheckpointEvent(tmpDir, makeEvent(`cp-${String(i).padStart(3, '0')}`));
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const events = readCheckpointEvents(tmpDir);
|
|
172
|
-
expect(events).toHaveLength(5);
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
describe('exports', () => {
|
|
177
|
-
it('should export from main index', () => {
|
|
178
|
-
expect(indexAppend).toBe(appendCheckpointEvent);
|
|
179
|
-
expect(indexRead).toBe(readCheckpointEvents);
|
|
180
|
-
expect(indexEventsFile).toBe(SESSIONLOG_EVENTS_FILE);
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
});
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for prepareTranscript flush sentinel (Claude Code agent)
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
6
|
-
import * as fs from 'node:fs';
|
|
7
|
-
import * as path from 'node:path';
|
|
8
|
-
import * as os from 'node:os';
|
|
9
|
-
import { createClaudeCodeAgent } from '../agent/agents/claude-code.js';
|
|
10
|
-
import { hasTranscriptPreparer } from '../agent/types.js';
|
|
11
|
-
|
|
12
|
-
describe('Claude Code prepareTranscript', () => {
|
|
13
|
-
let tmpDir: string;
|
|
14
|
-
const agent = createClaudeCodeAgent();
|
|
15
|
-
|
|
16
|
-
beforeEach(() => {
|
|
17
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'flush-sentinel-'));
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
afterEach(() => {
|
|
21
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should implement TranscriptPreparer', () => {
|
|
25
|
-
expect(hasTranscriptPreparer(agent)).toBe(true);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('should resolve quickly when sentinel is present', async () => {
|
|
29
|
-
const transcriptPath = path.join(tmpDir, 'session.jsonl');
|
|
30
|
-
const now = new Date().toISOString();
|
|
31
|
-
|
|
32
|
-
// Write a transcript with the stop hook sentinel
|
|
33
|
-
const lines = [
|
|
34
|
-
JSON.stringify({ type: 'user', message: { content: 'hello' }, timestamp: now }),
|
|
35
|
-
JSON.stringify({
|
|
36
|
-
type: 'assistant',
|
|
37
|
-
message: { content: [{ type: 'text', text: 'hi' }] },
|
|
38
|
-
timestamp: now,
|
|
39
|
-
}),
|
|
40
|
-
JSON.stringify({ type: 'hook_progress', message: 'hooks claude-code stop', timestamp: now }),
|
|
41
|
-
];
|
|
42
|
-
fs.writeFileSync(transcriptPath, lines.join('\n') + '\n');
|
|
43
|
-
|
|
44
|
-
const start = Date.now();
|
|
45
|
-
await agent.prepareTranscript(transcriptPath);
|
|
46
|
-
const elapsed = Date.now() - start;
|
|
47
|
-
|
|
48
|
-
// Should find sentinel quickly (well under the 3s timeout)
|
|
49
|
-
expect(elapsed).toBeLessThan(1000);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('should timeout gracefully when sentinel is missing', async () => {
|
|
53
|
-
const transcriptPath = path.join(tmpDir, 'session.jsonl');
|
|
54
|
-
|
|
55
|
-
// Write transcript WITHOUT sentinel
|
|
56
|
-
const lines = [
|
|
57
|
-
JSON.stringify({
|
|
58
|
-
type: 'user',
|
|
59
|
-
message: { content: 'hello' },
|
|
60
|
-
timestamp: new Date().toISOString(),
|
|
61
|
-
}),
|
|
62
|
-
];
|
|
63
|
-
fs.writeFileSync(transcriptPath, lines.join('\n') + '\n');
|
|
64
|
-
|
|
65
|
-
const start = Date.now();
|
|
66
|
-
await agent.prepareTranscript(transcriptPath);
|
|
67
|
-
const elapsed = Date.now() - start;
|
|
68
|
-
|
|
69
|
-
// Should wait up to ~3s then proceed
|
|
70
|
-
expect(elapsed).toBeGreaterThanOrEqual(2500);
|
|
71
|
-
expect(elapsed).toBeLessThan(5000);
|
|
72
|
-
}, 10000);
|
|
73
|
-
|
|
74
|
-
it('should timeout gracefully when file does not exist', async () => {
|
|
75
|
-
const start = Date.now();
|
|
76
|
-
await agent.prepareTranscript(path.join(tmpDir, 'nonexistent.jsonl'));
|
|
77
|
-
const elapsed = Date.now() - start;
|
|
78
|
-
|
|
79
|
-
// Should wait up to ~3s then proceed
|
|
80
|
-
expect(elapsed).toBeGreaterThanOrEqual(2500);
|
|
81
|
-
expect(elapsed).toBeLessThan(5000);
|
|
82
|
-
}, 10000);
|
|
83
|
-
|
|
84
|
-
it('should ignore sentinel with old timestamp', async () => {
|
|
85
|
-
const transcriptPath = path.join(tmpDir, 'session.jsonl');
|
|
86
|
-
|
|
87
|
-
// Write a sentinel with a very old timestamp
|
|
88
|
-
const oldTimestamp = new Date(Date.now() - 60_000).toISOString();
|
|
89
|
-
const lines = [
|
|
90
|
-
JSON.stringify({
|
|
91
|
-
type: 'hook_progress',
|
|
92
|
-
message: 'hooks claude-code stop',
|
|
93
|
-
timestamp: oldTimestamp,
|
|
94
|
-
}),
|
|
95
|
-
];
|
|
96
|
-
fs.writeFileSync(transcriptPath, lines.join('\n') + '\n');
|
|
97
|
-
|
|
98
|
-
const start = Date.now();
|
|
99
|
-
await agent.prepareTranscript(transcriptPath);
|
|
100
|
-
const elapsed = Date.now() - start;
|
|
101
|
-
|
|
102
|
-
// Old sentinel should be ignored, so we should timeout
|
|
103
|
-
expect(elapsed).toBeGreaterThanOrEqual(2500);
|
|
104
|
-
}, 10000);
|
|
105
|
-
});
|
|
@@ -1,375 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for Gemini CLI Agent
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
6
|
-
import * as fs from 'node:fs';
|
|
7
|
-
import * as path from 'node:path';
|
|
8
|
-
import * as os from 'node:os';
|
|
9
|
-
import { createGeminiCLIAgent, parseGeminiTranscript } from '../agent/agents/gemini-cli.js';
|
|
10
|
-
import { EventType } from '../types.js';
|
|
11
|
-
|
|
12
|
-
describe('Gemini CLI Agent', () => {
|
|
13
|
-
const agent = createGeminiCLIAgent();
|
|
14
|
-
|
|
15
|
-
describe('basic properties', () => {
|
|
16
|
-
it('should have correct name and type', () => {
|
|
17
|
-
expect(agent.name).toBe('gemini');
|
|
18
|
-
expect(agent.type).toBe('Gemini CLI');
|
|
19
|
-
expect(agent.isPreview).toBe(true);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('should protect .gemini directory', () => {
|
|
23
|
-
expect(agent.protectedDirs).toContain('.gemini');
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
describe('detectPresence', () => {
|
|
28
|
-
let tmpDir: string;
|
|
29
|
-
|
|
30
|
-
beforeEach(() => {
|
|
31
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gemini-test-'));
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
afterEach(() => {
|
|
35
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('should detect presence when .gemini dir exists', async () => {
|
|
39
|
-
fs.mkdirSync(path.join(tmpDir, '.gemini'));
|
|
40
|
-
expect(await agent.detectPresence(tmpDir)).toBe(true);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('should return false when .gemini dir does not exist', async () => {
|
|
44
|
-
expect(await agent.detectPresence(tmpDir)).toBe(false);
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
describe('formatResumeCommand', () => {
|
|
49
|
-
it('should include session ID', () => {
|
|
50
|
-
const cmd = agent.formatResumeCommand('sess-123');
|
|
51
|
-
expect(cmd).toContain('sess-123');
|
|
52
|
-
expect(cmd).toContain('gemini');
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
describe('hookNames', () => {
|
|
57
|
-
it('should return all 11 hooks', () => {
|
|
58
|
-
const names = agent.hookNames();
|
|
59
|
-
expect(names).toHaveLength(11);
|
|
60
|
-
expect(names).toContain('session-start');
|
|
61
|
-
expect(names).toContain('session-end');
|
|
62
|
-
expect(names).toContain('before-agent');
|
|
63
|
-
expect(names).toContain('after-agent');
|
|
64
|
-
expect(names).toContain('before-model');
|
|
65
|
-
expect(names).toContain('after-model');
|
|
66
|
-
expect(names).toContain('pre-compress');
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe('parseHookEvent', () => {
|
|
71
|
-
it('should parse session-start event', () => {
|
|
72
|
-
const stdin = JSON.stringify({ session_id: 'gem-123' });
|
|
73
|
-
const event = agent.parseHookEvent('session-start', stdin);
|
|
74
|
-
expect(event).not.toBeNull();
|
|
75
|
-
expect(event!.type).toBe(EventType.SessionStart);
|
|
76
|
-
expect(event!.sessionID).toBe('gem-123');
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('should parse before-agent as TurnStart', () => {
|
|
80
|
-
const stdin = JSON.stringify({
|
|
81
|
-
session_id: 'gem-456',
|
|
82
|
-
prompt: 'Add a function',
|
|
83
|
-
});
|
|
84
|
-
const event = agent.parseHookEvent('before-agent', stdin);
|
|
85
|
-
expect(event).not.toBeNull();
|
|
86
|
-
expect(event!.type).toBe(EventType.TurnStart);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it('should parse after-agent as TurnEnd', () => {
|
|
90
|
-
const stdin = JSON.stringify({ session_id: 'gem-789' });
|
|
91
|
-
const event = agent.parseHookEvent('after-agent', stdin);
|
|
92
|
-
expect(event).not.toBeNull();
|
|
93
|
-
expect(event!.type).toBe(EventType.TurnEnd);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('should parse pre-compress as Compaction', () => {
|
|
97
|
-
const stdin = JSON.stringify({ session_id: 'gem-111' });
|
|
98
|
-
const event = agent.parseHookEvent('pre-compress', stdin);
|
|
99
|
-
expect(event).not.toBeNull();
|
|
100
|
-
expect(event!.type).toBe(EventType.Compaction);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it('should return null for pass-through hooks', () => {
|
|
104
|
-
const stdin = JSON.stringify({ session_id: 'gem-222' });
|
|
105
|
-
expect(agent.parseHookEvent('before-tool', stdin)).toBeNull();
|
|
106
|
-
expect(agent.parseHookEvent('after-tool', stdin)).toBeNull();
|
|
107
|
-
expect(agent.parseHookEvent('before-model', stdin)).toBeNull();
|
|
108
|
-
expect(agent.parseHookEvent('notification', stdin)).toBeNull();
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('should return null for invalid JSON', () => {
|
|
112
|
-
expect(agent.parseHookEvent('session-start', 'bad')).toBeNull();
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
describe('parseGeminiTranscript', () => {
|
|
117
|
-
it('should parse string content', () => {
|
|
118
|
-
const data = JSON.stringify({
|
|
119
|
-
messages: [
|
|
120
|
-
{ type: 'user', content: 'Hello' },
|
|
121
|
-
{ type: 'gemini', content: 'Hi there' },
|
|
122
|
-
],
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
const transcript = parseGeminiTranscript(data);
|
|
126
|
-
expect(transcript.messages).toHaveLength(2);
|
|
127
|
-
expect(transcript.messages[0].content).toBe('Hello');
|
|
128
|
-
expect(transcript.messages[1].content).toBe('Hi there');
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it('should parse array content (text parts)', () => {
|
|
132
|
-
const data = JSON.stringify({
|
|
133
|
-
messages: [
|
|
134
|
-
{
|
|
135
|
-
type: 'gemini',
|
|
136
|
-
content: [{ text: 'Part 1' }, { text: 'Part 2' }],
|
|
137
|
-
},
|
|
138
|
-
],
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
const transcript = parseGeminiTranscript(data);
|
|
142
|
-
expect(transcript.messages[0].content).toBe('Part 1\nPart 2');
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it('should handle empty messages array', () => {
|
|
146
|
-
const data = JSON.stringify({ messages: [] });
|
|
147
|
-
const transcript = parseGeminiTranscript(data);
|
|
148
|
-
expect(transcript.messages).toHaveLength(0);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
it('should preserve tool calls', () => {
|
|
152
|
-
const data = JSON.stringify({
|
|
153
|
-
messages: [
|
|
154
|
-
{
|
|
155
|
-
type: 'gemini',
|
|
156
|
-
content: 'Working on it...',
|
|
157
|
-
toolCalls: [{ id: 'tc1', name: 'edit_file', args: { path: 'foo.ts' } }],
|
|
158
|
-
},
|
|
159
|
-
],
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
const transcript = parseGeminiTranscript(data);
|
|
163
|
-
expect(transcript.messages[0].toolCalls).toHaveLength(1);
|
|
164
|
-
expect(transcript.messages[0].toolCalls![0].name).toBe('edit_file');
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
describe('hook installation', () => {
|
|
169
|
-
let tmpDir: string;
|
|
170
|
-
|
|
171
|
-
beforeEach(() => {
|
|
172
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gemini-hooks-'));
|
|
173
|
-
fs.mkdirSync(path.join(tmpDir, '.gemini'), { recursive: true });
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
afterEach(() => {
|
|
177
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it('should install hooks to .gemini/settings.json', async () => {
|
|
181
|
-
const count = await agent.installHooks(tmpDir);
|
|
182
|
-
expect(count).toBe(12);
|
|
183
|
-
|
|
184
|
-
const settingsPath = path.join(tmpDir, '.gemini', 'settings.json');
|
|
185
|
-
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
186
|
-
expect(settings.hooksConfig.enabled).toBe(true);
|
|
187
|
-
expect(settings.hooks).toBeDefined();
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
it('should be idempotent', async () => {
|
|
191
|
-
await agent.installHooks(tmpDir);
|
|
192
|
-
const count = await agent.installHooks(tmpDir);
|
|
193
|
-
expect(count).toBe(0);
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it('should report hooks as installed', async () => {
|
|
197
|
-
expect(await agent.areHooksInstalled(tmpDir)).toBe(false);
|
|
198
|
-
await agent.installHooks(tmpDir);
|
|
199
|
-
expect(await agent.areHooksInstalled(tmpDir)).toBe(true);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
it('should uninstall hooks', async () => {
|
|
203
|
-
await agent.installHooks(tmpDir);
|
|
204
|
-
await agent.uninstallHooks(tmpDir);
|
|
205
|
-
expect(await agent.areHooksInstalled(tmpDir)).toBe(false);
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
describe('TranscriptAnalyzer', () => {
|
|
210
|
-
let tmpDir: string;
|
|
211
|
-
|
|
212
|
-
beforeEach(() => {
|
|
213
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gemini-transcript-'));
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
afterEach(() => {
|
|
217
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
it('should get transcript position', async () => {
|
|
221
|
-
const transcriptPath = path.join(tmpDir, 'session.json');
|
|
222
|
-
fs.writeFileSync(
|
|
223
|
-
transcriptPath,
|
|
224
|
-
JSON.stringify({
|
|
225
|
-
messages: [
|
|
226
|
-
{ type: 'user', content: 'Hello' },
|
|
227
|
-
{ type: 'gemini', content: 'Hi' },
|
|
228
|
-
{ type: 'user', content: 'Thanks' },
|
|
229
|
-
],
|
|
230
|
-
}),
|
|
231
|
-
);
|
|
232
|
-
|
|
233
|
-
const pos = await agent.getTranscriptPosition(transcriptPath);
|
|
234
|
-
expect(pos).toBe(3);
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
it('should extract modified files from offset', async () => {
|
|
238
|
-
const transcriptPath = path.join(tmpDir, 'session.json');
|
|
239
|
-
fs.writeFileSync(
|
|
240
|
-
transcriptPath,
|
|
241
|
-
JSON.stringify({
|
|
242
|
-
messages: [
|
|
243
|
-
{ type: 'user', content: 'Fix the file' },
|
|
244
|
-
{
|
|
245
|
-
type: 'gemini',
|
|
246
|
-
content: 'Done',
|
|
247
|
-
toolCalls: [
|
|
248
|
-
{ id: 'tc1', name: 'edit_file', args: { file_path: 'src/app.ts' } },
|
|
249
|
-
{ id: 'tc2', name: 'write_file', args: { path: 'src/utils.ts' } },
|
|
250
|
-
],
|
|
251
|
-
},
|
|
252
|
-
],
|
|
253
|
-
}),
|
|
254
|
-
);
|
|
255
|
-
|
|
256
|
-
const result = await agent.extractModifiedFilesFromOffset(transcriptPath, 0);
|
|
257
|
-
expect(result.files).toContain('src/app.ts');
|
|
258
|
-
expect(result.files).toContain('src/utils.ts');
|
|
259
|
-
expect(result.currentPosition).toBe(2);
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
it('should extract prompts from offset', async () => {
|
|
263
|
-
const transcriptPath = path.join(tmpDir, 'session.json');
|
|
264
|
-
fs.writeFileSync(
|
|
265
|
-
transcriptPath,
|
|
266
|
-
JSON.stringify({
|
|
267
|
-
messages: [
|
|
268
|
-
{ type: 'user', content: 'First prompt' },
|
|
269
|
-
{ type: 'gemini', content: 'Response' },
|
|
270
|
-
{ type: 'user', content: 'Second prompt' },
|
|
271
|
-
],
|
|
272
|
-
}),
|
|
273
|
-
);
|
|
274
|
-
|
|
275
|
-
const prompts = await agent.extractPrompts(transcriptPath, 0);
|
|
276
|
-
expect(prompts).toEqual(['First prompt', 'Second prompt']);
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
it('should extract prompts from specific offset', async () => {
|
|
280
|
-
const transcriptPath = path.join(tmpDir, 'session.json');
|
|
281
|
-
fs.writeFileSync(
|
|
282
|
-
transcriptPath,
|
|
283
|
-
JSON.stringify({
|
|
284
|
-
messages: [
|
|
285
|
-
{ type: 'user', content: 'Old prompt' },
|
|
286
|
-
{ type: 'gemini', content: 'Response' },
|
|
287
|
-
{ type: 'user', content: 'New prompt' },
|
|
288
|
-
],
|
|
289
|
-
}),
|
|
290
|
-
);
|
|
291
|
-
|
|
292
|
-
const prompts = await agent.extractPrompts(transcriptPath, 2);
|
|
293
|
-
expect(prompts).toEqual(['New prompt']);
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
it('should extract last assistant response as summary', async () => {
|
|
297
|
-
const transcriptPath = path.join(tmpDir, 'session.json');
|
|
298
|
-
fs.writeFileSync(
|
|
299
|
-
transcriptPath,
|
|
300
|
-
JSON.stringify({
|
|
301
|
-
messages: [
|
|
302
|
-
{ type: 'user', content: 'Do something' },
|
|
303
|
-
{ type: 'gemini', content: 'First response' },
|
|
304
|
-
{ type: 'user', content: 'More' },
|
|
305
|
-
{ type: 'gemini', content: 'Final response' },
|
|
306
|
-
],
|
|
307
|
-
}),
|
|
308
|
-
);
|
|
309
|
-
|
|
310
|
-
const summary = await agent.extractSummary(transcriptPath);
|
|
311
|
-
expect(summary).toBe('Final response');
|
|
312
|
-
});
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
describe('TokenCalculator', () => {
|
|
316
|
-
it('should calculate token usage from transcript', async () => {
|
|
317
|
-
const data = Buffer.from(
|
|
318
|
-
JSON.stringify({
|
|
319
|
-
messages: [
|
|
320
|
-
{ type: 'user', content: 'Hello' },
|
|
321
|
-
{ type: 'gemini', content: 'Hi', tokens: { input: 100, output: 50, cached: 10 } },
|
|
322
|
-
{ type: 'user', content: 'More' },
|
|
323
|
-
{ type: 'gemini', content: 'Done', tokens: { input: 200, output: 100, cached: 20 } },
|
|
324
|
-
],
|
|
325
|
-
}),
|
|
326
|
-
);
|
|
327
|
-
|
|
328
|
-
const usage = await agent.calculateTokenUsage(data, 0);
|
|
329
|
-
expect(usage.inputTokens).toBe(300);
|
|
330
|
-
expect(usage.outputTokens).toBe(150);
|
|
331
|
-
expect(usage.cacheReadTokens).toBe(30);
|
|
332
|
-
expect(usage.apiCallCount).toBe(2);
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
it('should calculate from offset', async () => {
|
|
336
|
-
const data = Buffer.from(
|
|
337
|
-
JSON.stringify({
|
|
338
|
-
messages: [
|
|
339
|
-
{ type: 'gemini', content: 'Old', tokens: { input: 100, output: 50, cached: 0 } },
|
|
340
|
-
{ type: 'gemini', content: 'New', tokens: { input: 200, output: 100, cached: 0 } },
|
|
341
|
-
],
|
|
342
|
-
}),
|
|
343
|
-
);
|
|
344
|
-
|
|
345
|
-
const usage = await agent.calculateTokenUsage(data, 1);
|
|
346
|
-
expect(usage.inputTokens).toBe(200);
|
|
347
|
-
expect(usage.outputTokens).toBe(100);
|
|
348
|
-
expect(usage.apiCallCount).toBe(1);
|
|
349
|
-
});
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
describe('TranscriptChunker', () => {
|
|
353
|
-
it('should chunk large transcripts', async () => {
|
|
354
|
-
const messages = Array.from({ length: 50 }, (_, i) => ({
|
|
355
|
-
type: i % 2 === 0 ? 'user' : 'gemini',
|
|
356
|
-
content: 'x'.repeat(100),
|
|
357
|
-
}));
|
|
358
|
-
const content = Buffer.from(JSON.stringify({ messages }));
|
|
359
|
-
const chunks = await agent.chunkTranscript(content, 500);
|
|
360
|
-
expect(chunks.length).toBeGreaterThan(1);
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
it('should reassemble chunks back', async () => {
|
|
364
|
-
const messages = [
|
|
365
|
-
{ type: 'user', content: 'Hello' },
|
|
366
|
-
{ type: 'gemini', content: 'World' },
|
|
367
|
-
];
|
|
368
|
-
const content = Buffer.from(JSON.stringify({ messages }));
|
|
369
|
-
const chunks = await agent.chunkTranscript(content, 50);
|
|
370
|
-
const reassembled = await agent.reassembleTranscript(chunks);
|
|
371
|
-
const parsed = JSON.parse(reassembled.toString('utf-8'));
|
|
372
|
-
expect(parsed.messages).toHaveLength(2);
|
|
373
|
-
});
|
|
374
|
-
});
|
|
375
|
-
});
|