@kjerneverk/agentic 1.0.5-dev.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.
Files changed (58) hide show
  1. package/.kodrdriv-test-cache.json +6 -0
  2. package/LICENSE +18 -0
  3. package/README.md +167 -0
  4. package/SECURITY.md +94 -0
  5. package/dist/index.d.ts +770 -0
  6. package/dist/index.js +1822 -0
  7. package/dist/index.js.map +1 -0
  8. package/output/kodrdriv/260110-1207-commit-message.md +1 -0
  9. package/output/kodrdriv/260110-1208-commit-message.md +1 -0
  10. package/output/kodrdriv/260110-1210-release-notes.md +27 -0
  11. package/output/kodrdriv/260110-1232-commit-message.md +1 -0
  12. package/output/kodrdriv/260110-1234-release-notes.md +46 -0
  13. package/output/kodrdriv/260110-1308-release-notes.md +20 -0
  14. package/output/kodrdriv/260112-2155-commit-message.md +1 -0
  15. package/output/kodrdriv/260112-2156-release-notes.md +33 -0
  16. package/output/kodrdriv/260112-2340-commit-message.md +1 -0
  17. package/output/kodrdriv/260113-0017-commit-message.md +1 -0
  18. package/output/kodrdriv/260113-0017-release-notes.md +53 -0
  19. package/output/kodrdriv/260115-0616-commit-message.md +4 -0
  20. package/output/kodrdriv/260115-0739-commit-message.md +1 -0
  21. package/output/kodrdriv/260115-0746-commit-message.md +1 -0
  22. package/output/kodrdriv/260115-0747-release-notes.md +91 -0
  23. package/output/kodrdriv/260126-0851-commit-message.md +1 -0
  24. package/output/kodrdriv/260128-0900-commit-message.md +1 -0
  25. package/output/kodrdriv/260128-0900-release-notes.md +29 -0
  26. package/output/kodrdriv/260128-0905-commit-message.md +1 -0
  27. package/output/kodrdriv/260128-0913-commit-message.md +1 -0
  28. package/output/kodrdriv/260128-0913-release-notes.md +23 -0
  29. package/output/kodrdriv/260128-0919-commit-message.md +1 -0
  30. package/output/kodrdriv/260128-0919-release-notes.md +21 -0
  31. package/output/kodrdriv/260130-1642-commit-message.md +1 -0
  32. package/output/kodrdriv/260130-1642-release-notes.md +29 -0
  33. package/output/kodrdriv/RELEASE_NOTES.md +27 -0
  34. package/output/kodrdriv/RELEASE_TITLE.md +1 -0
  35. package/output/kodrdriv/agentic-reflection-commit-2026-01-10T19-18-11-913Z.md +187 -0
  36. package/output/kodrdriv/agentic-reflection-commit-2026-01-10T20-03-27-409Z.md +121 -0
  37. package/output/kodrdriv/agentic-reflection-commit-2026-01-10T20-07-27-813Z.md +114 -0
  38. package/output/kodrdriv/agentic-reflection-commit-2026-01-10T20-08-06-279Z.md +97 -0
  39. package/output/kodrdriv/agentic-reflection-commit-2026-01-10T20-32-25-791Z.md +114 -0
  40. package/output/kodrdriv/agentic-reflection-commit-2026-01-13T05-55-30-733Z.md +97 -0
  41. package/output/kodrdriv/agentic-reflection-commit-2026-01-13T07-40-28-878Z.md +97 -0
  42. package/output/kodrdriv/agentic-reflection-commit-2026-01-13T08-17-22-230Z.md +114 -0
  43. package/output/kodrdriv/agentic-reflection-commit-2026-01-14T14-55-10-122Z.md +177 -0
  44. package/output/kodrdriv/agentic-reflection-commit-2026-01-15T14-16-05-605Z.md +100 -0
  45. package/output/kodrdriv/agentic-reflection-commit-2026-01-15T15-39-32-200Z.md +97 -0
  46. package/output/kodrdriv/agentic-reflection-commit-2026-01-15T15-46-32-840Z.md +114 -0
  47. package/output/kodrdriv/agentic-reflection-commit-2026-01-26T16-51-00-446Z.md +152 -0
  48. package/output/kodrdriv/agentic-reflection-commit-2026-01-31T00-38-59-868Z.md +236 -0
  49. package/output/kodrdriv/agentic-reflection-commit-2026-01-31T00-42-31-993Z.md +152 -0
  50. package/output/kodrdriv/agentic-reflection-release-2026-01-10T20-10-49-531Z.md +329 -0
  51. package/output/kodrdriv/agentic-reflection-release-2026-01-10T20-34-32-038Z.md +319 -0
  52. package/output/kodrdriv/agentic-reflection-release-2026-01-10T21-08-36-314Z.md +168 -0
  53. package/output/kodrdriv/agentic-reflection-release-2026-01-13T05-56-04-802Z.md +264 -0
  54. package/output/kodrdriv/agentic-reflection-release-2026-01-13T08-17-56-556Z.md +255 -0
  55. package/output/kodrdriv/agentic-reflection-release-2026-01-15T15-47-32-509Z.md +460 -0
  56. package/output/kodrdriv/agentic-reflection-release-2026-01-31T00-42-59-683Z.md +400 -0
  57. package/package.json +59 -0
  58. package/package.json~ +58 -0
@@ -0,0 +1,319 @@
1
+ # Agentic Workflow - Self-Reflection Report
2
+
3
+ Generated: 2026-01-10T20:34:32.038Z
4
+
5
+ ## Execution Summary
6
+
7
+ - **Iterations**: 4
8
+ - **Tool Calls**: 11
9
+ - **Unique Tools**: 6
10
+
11
+ ## Tool Effectiveness Analysis
12
+
13
+ | Tool | Calls | Success | Failures | Success Rate | Avg Duration |
14
+ |------|-------|---------|----------|--------------|--------------|
15
+ | get_file_content | 5 | 5 | 0 | 100.0% | 1ms |
16
+ | search_codebase | 3 | 2 | 1 | 66.7% | 12ms |
17
+ | get_release_stats | 1 | 1 | 0 | 100.0% | 53ms |
18
+ | analyze_commit_patterns | 1 | 1 | 0 | 100.0% | 11ms |
19
+ | get_breaking_changes | 1 | 1 | 0 | 100.0% | 22ms |
20
+ | get_tag_history | 1 | 1 | 0 | 100.0% | 48ms |
21
+
22
+ ### Tool Performance Insights
23
+
24
+ **Tools with Failures:**
25
+ - search_codebase: 1/3 failures (33.3%)
26
+
27
+ **Most Frequently Used:**
28
+ - get_release_stats: 1 calls
29
+ - analyze_commit_patterns: 1 calls
30
+ - get_breaking_changes: 1 calls
31
+
32
+ ## Recommendations for Improvement
33
+
34
+ - **Tool Failures**: Investigate and fix tools that are failing. This may indicate issues with error handling or tool implementation.
35
+ - **Underutilized Tools**: Many tools were called only once. Consider whether all tools are necessary or if the agent needs better guidance on when to use them.
36
+
37
+ ## Detailed Execution Timeline
38
+
39
+ | Time | Iteration | Tool | Result | Duration |
40
+ |------|-----------|------|--------|----------|
41
+ | 12:32:55 PM | 1 | get_release_stats | ✅ Success | 53ms |
42
+ | 12:32:55 PM | 1 | analyze_commit_patterns | ✅ Success | 11ms |
43
+ | 12:32:56 PM | 1 | get_breaking_changes | ✅ Success | 22ms |
44
+ | 12:32:56 PM | 1 | get_tag_history | ✅ Success | 48ms |
45
+ | 12:33:07 PM | 2 | get_file_content | ✅ Success | 1ms |
46
+ | 12:33:07 PM | 2 | get_file_content | ✅ Success | 0ms |
47
+ | 12:33:07 PM | 2 | search_codebase | ✅ Success | 13ms |
48
+ | 12:33:07 PM | 2 | search_codebase | ❌ Tool "search_codebase" execution failed: Search failed: Command failed: git grep -n -C 2 "export .*zod|z\." -- '*.ts'
49
+ | 11ms |
50
+ | 12:33:27 PM | 3 | search_codebase | ✅ Success | 12ms |
51
+ | 12:33:27 PM | 3 | get_file_content | ✅ Success | 1ms |
52
+ | 12:33:27 PM | 3 | get_file_content | ✅ Success | 0ms |
53
+ | 12:33:27 PM | 3 | get_file_content | ✅ Success | 1ms |
54
+
55
+ ## Conversation History
56
+
57
+ <details>
58
+ <summary>Click to expand full agentic interaction</summary>
59
+
60
+ ```json
61
+ [
62
+ {
63
+ "role": "system",
64
+ "content": "You are a professional software engineer writing release notes for your team and users.\n\n## Available Tools\n\n### General\n\n**get_file_history**\nGet git commit history for one or more files to understand their evolution and past changes\n\nParameters:\n- `filePaths` (required): Array of file paths to get history for\n- `limit`: Maximum number of commits to return (default: 10)\n- `format`: Output format: \"summary\" for brief or \"detailed\" for full messages\n\n**When to use:** Get git commit history for one or more files to understand their evolution and past changes\n\n---\n\n**get_file_content**\nGet the complete current content of a file to understand context around changes. Returns a message if the file does not exist (e.g., if it was deleted).\n\nParameters:\n- `filePath` (required): Path to the file\n- `includeLineNumbers`: Include line numbers in output (default: false)\n\n**When to use:** Get the complete current content of a file to understand context around changes. Returns a message if the file does not exist (e.g., if it was deleted).\n\n---\n\n**search_codebase**\nSearch for code patterns, function names, or text across the codebase using git grep\n\nParameters:\n- `query` (required): Search pattern (can be plain text or regex)\n- `fileTypes`: Limit search to specific file extensions (e.g., [\"ts\", \"js\"])\n- `contextLines`: Number of context lines to show around matches (default: 2)\n\n**When to use:** Search for code patterns, function names, or text across the codebase using git grep\n\n---\n\n**get_related_tests**\nFind test files related to production files to understand what the code is supposed to do\n\nParameters:\n- `filePaths` (required): Production file paths\n\n**When to use:** Find test files related to production files to understand what the code is supposed to do\n\n---\n\n**get_file_dependencies**\nFind which files import or depend on the changed files to assess change impact\n\nParameters:\n- `filePaths` (required): Files to analyze dependencies for\n\n**When to use:** Find which files import or depend on the changed files to assess change impact\n\n---\n\n**analyze_diff_section**\nGet expanded context around specific lines in a file to better understand changes\n\nParameters:\n- `filePath` (required): File containing the section to analyze\n- `startLine` (required): Starting line number\n- `endLine` (required): Ending line number\n- `contextLines`: Number of additional context lines to show before and after (default: 10)\n\n**When to use:** Get expanded context around specific lines in a file to better understand changes\n\n---\n\n**get_recent_commits**\nGet recent commits that modified the same files to understand recent work in this area\n\nParameters:\n- `filePaths` (required): Files to check for recent commits\n- `since`: Time period to look back (e.g., \"1 week ago\", \"2 days ago\")\n- `limit`: Maximum number of commits to return (default: 5)\n\n**When to use:** Get recent commits that modified the same files to understand recent work in this area\n\n---\n\n**group_files_by_concern**\nAnalyze changed files and suggest logical groupings that might represent separate concerns\n\nParameters:\n- `filePaths` (required): All changed files to analyze\n\n**When to use:** Analyze changed files and suggest logical groupings that might represent separate concerns\n\n---\n\n### Release Analysis\n\n**get_tag_history** _(cheap)_\nGet the history of previous release tags to understand release patterns and versioning\n\nParameters:\n- `limit`: Number of recent tags to retrieve (default: 10)\n- `pattern`: Filter tags by pattern (e.g., \"v*\" for version tags)\n\n**When to use:** Get the history of previous release tags to understand release patterns and versioning\n\n**Examples:**\n- Check recent version tags: `get_tag_history({\"limit\":5,\"pattern\":\"v*\"})`\n\n---\n\n**compare_previous_release** _(moderate)_\nCompare this release with a previous release to understand what changed between versions\n\nParameters:\n- `previousTag` (required): Previous release tag to compare against\n- `currentRef`: Current reference (default: HEAD)\n- `statsOnly`: Return only statistics, not full diff (default: true)\n\n**When to use:** Compare this release with a previous release to understand what changed between versions\n\n**Examples:**\n- Compare with last release: `compare_previous_release({\"previousTag\":\"v1.0.0\",\"currentRef\":\"HEAD\"})`\n\n---\n\n**get_release_stats** _(moderate)_\nGet comprehensive statistics about the release including contributors, file changes, and commit patterns\n\nParameters:\n- `fromRef` (required): Starting reference for the release range\n- `toRef`: Ending reference for the release range (default: HEAD)\n\n**When to use:** Get comprehensive statistics about the release including contributors, file changes, and commit patterns\n\n**Examples:**\n- Get release overview: `get_release_stats({\"fromRef\":\"v1.0.0\",\"toRef\":\"HEAD\"})`\n\n---\n\n**get_breaking_changes** _(expensive)_\nSearch for potential breaking changes by looking for specific patterns in commits and diffs\n\nParameters:\n- `fromRef` (required): Starting reference for the release range\n- `toRef`: Ending reference for the release range (default: HEAD)\n\n**When to use:** Search for potential breaking changes by looking for specific patterns in commits and diffs\n\n**Examples:**\n- Check for breaking changes: `get_breaking_changes({\"fromRef\":\"v1.0.0\",\"toRef\":\"HEAD\"})`\n\n---\n\n**analyze_commit_patterns** _(cheap)_\nAnalyze commit messages to identify patterns and themes in the release\n\nParameters:\n- `fromRef` (required): Starting reference for the release range\n- `toRef`: Ending reference for the release range (default: HEAD)\n\n**When to use:** Analyze commit messages to identify patterns and themes in the release\n\n**Examples:**\n- Find commit themes: `analyze_commit_patterns({\"fromRef\":\"v1.0.0\",\"toRef\":\"HEAD\"})`\n\n---\n\n\n\n## Your Task\n\nWrite release notes that clearly explain what's in this release and why it matters. Your notes should help users and developers understand what changed without needing to read every commit.\n\nFocus on:\n- What problems does this release solve?\n- What new capabilities does it add?\n- What's the impact on users and developers?\n- Are there breaking changes or important considerations?\n\nUse the available tools to investigate the changes. The more you understand, the better your notes will be.\n\n**Important**: If additional context is provided (from context files or other sources), use your judgment:\n- If the context is relevant to this specific package/release, incorporate it appropriately\n- If the context describes changes in other packages or unrelated work, ignore it\n- Don't fabricate connections between this package and unrelated context\n- Be honest about what changed - only mention what actually happened in this release\n- Context is supplemental information, not a requirement to include\n\n## Investigation Approach\n\nUse tools based on what you need to know:\n\n**Context:**\n- get_tag_history - understand release patterns\n- get_release_stats - quantify scope\n- compare_previous_release - see how this compares\n\n**Understanding:**\n- group_files_by_concern - identify themes\n- analyze_commit_patterns - detect patterns\n- get_file_content - see full context\n- analyze_diff_section - expand unclear changes\n- get_file_history - understand evolution\n\n**Impact:**\n- get_file_dependencies - assess reach\n- search_codebase - find usage patterns\n- get_related_tests - understand behavior changes\n- get_breaking_changes - identify breaking changes (always use)\n\n## Writing Style\n\nWrite naturally and directly:\n- Use plain language that users can understand\n- Be specific about what changed and why\n- Avoid marketing speak and buzzwords\n- No emojis or excessive punctuation\n- No phrases like \"we're excited to announce\"\n- No meta-commentary about the release itself\n- Focus on facts and implications, not enthusiasm\n\nStructure your notes logically:\n- Start with the most important changes\n- Group related changes together\n- Explain breaking changes clearly\n- Include practical examples when helpful\n\n## Output Format\n\nWhen ready, format your response as JSON:\n\nRELEASE_NOTES:\n{\n \"title\": \"Clear, factual title describing the main changes\",\n \"body\": \"Detailed release notes in Markdown format\"\n}\n\nOutput only the JSON. No conversational remarks or follow-up offers."
65
+ },
66
+ {
67
+ "role": "user",
68
+ "content": "I need comprehensive release notes for changes from main to HEAD.\n\n## Commit Log\ncommit 9bae6b655de87c35f39963065583fbebf89407de\nAuthor: Tim O'Brien <tobrien@discursive.com>\nDate: Sat Jan 10 12:32:25 2026 -0800\n\n chore(release): bump version to 0.0.3\n\ncommit 3c66dd8209adf51047b8fa1f7a1e7c49eea73591\nAuthor: Tim O'Brien <tobrien@discursive.com>\nDate: Sat Jan 10 12:32:04 2026 -0800\n\n Separating tests from src and also making sure that test coverage reports are being generated\n\ncommit a1da8f0666207355bbe53c95b9db9161fefe69ac\nAuthor: Tim O'Brien <tobrien@discursive.com>\nDate: Sat Jan 10 12:23:27 2026 -0800\n\n 0.0.3-dev.0\n\n\n## Diff Summary\ndiff --git a/package.json b/package.json\nindex 6b5e17f..910c94a 100644\n--- a/package.json\n+++ b/package.json\n@@ -1,6 +1,6 @@\n {\n \"name\": \"@riotprompt/agentic\",\n- \"version\": \"0.0.2\",\n+ \"version\": \"0.0.3\",\n \"description\": \"Shared agentic framework for multi-turn AI conversations and tool orchestration\",\n \"type\": \"module\",\n \"main\": \"./dist/index.cjs\",\n@@ -16,8 +16,10 @@\n \"scripts\": {\n \"clean\": \"rm -rf dist\",\n \"build\": \"vite build\",\n- \"test\": \"vitest run\",\n+ \"test\": \"vitest run --coverage\",\n+ \"test:coverage\": \"vitest run --coverage\",\n \"lint\": \"eslint src\",\n+ \"precommit\": \"npm run lint && npm run test\",\n \"prepublishOnly\": \"npm run clean && npm run build\"\n },\n \"keywords\": [\n@@ -32,17 +34,18 @@\n \"author\": \"Tim O'Brien <tobrien@discursive.com>\",\n \"license\": \"Apache-2.0\",\n \"dependencies\": {\n- \"zod\": \"^3.25.51\"\n+ \"zod\": \"^4.3.5\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^25.0.6\",\n \"@typescript-eslint/eslint-plugin\": \"^8.33.1\",\n \"@typescript-eslint/parser\": \"^8.33.1\",\n+ \"@vitest/coverage-v8\": \"^4.0.16\",\n \"eslint\": \"^9.28.0\",\n- \"globals\": \"^16.2.0\",\n+ \"globals\": \"^17.0.0\",\n \"typescript\": \"^5.8.3\",\n \"vite\": \"^7.0.4\",\n \"vite-plugin-dts\": \"^4.5.4\",\n- \"vitest\": \"^3.2.4\"\n+ \"vitest\": \"^4.0.16\"\n }\n }\ndiff --git a/src/context-manager.test.ts b/tests/context-manager.test.ts\nsimilarity index 98%\nrename from src/context-manager.test.ts\nrename to tests/context-manager.test.ts\nindex e7e247d..e11eb59 100644\n--- a/src/context-manager.test.ts\n+++ b/tests/context-manager.test.ts\n@@ -1,6 +1,6 @@\n import { describe, it, expect, beforeEach } from 'vitest';\n-import { ContextManager, type ContextStats } from './context-manager';\n-import type { DynamicContentItem } from './types';\n+import { ContextManager, type ContextStats } from '../src/context-manager';\n+import type { DynamicContentItem } from '../src/types';\n \n describe('ContextManager', () => {\n let manager: ContextManager;\ndiff --git a/src/tools.test.ts b/tests/tools.test.ts\nsimilarity index 99%\nrename from src/tools.test.ts\nrename to tests/tools.test.ts\nindex 3bd2717..15f2661 100644\n--- a/src/tools.test.ts\n+++ b/tests/tools.test.ts\n@@ -1,5 +1,5 @@\n import { describe, it, expect, vi, beforeEach } from 'vitest';\n-import { ToolRegistry, type Tool, type ToolContext } from './tools';\n+import { ToolRegistry, type Tool, type ToolContext } from '../src/tools';\n \n describe('ToolRegistry', () => {\n let registry: ToolRegistry;\ndiff --git a/vitest.config.ts b/vitest.config.ts\nindex 9d8325f..c48ee66 100644\n--- a/vitest.config.ts\n+++ b/vitest.config.ts\n@@ -2,13 +2,20 @@ import { defineConfig } from \"vitest/config\";\n \n export default defineConfig({\n test: {\n- include: [\"src/**/*.test.ts\", \"tests/**/*.test.ts\"],\n+ include: [\"tests/**/*.test.ts\"],\n globals: true,\n coverage: {\n provider: \"v8\",\n- reporter: [\"text\", \"html\"],\n+ reporter: [\"text\", \"json\", \"html\"],\n include: [\"src/**/*.ts\"],\n- exclude: [\"src/**/*.test.ts\"],\n+ exclude: [\n+ \"src/**/*.test.ts\",\n+ \"node_modules/\",\n+ \"dist/**\",\n+ \"vitest.config.ts\",\n+ \"vite.config.ts\",\n+ \"eslint.config.mjs\",\n+ ],\n },\n },\n });\n\n\nAnalyze these changes and write clear release notes. Consider:\n- What's the main story of this release?\n- What problems does it solve?\n- What's the impact on users and developers?\n- Are there breaking changes?\n\nIf context information is provided, use it only if relevant to this specific package.\nDon't force connections that don't exist - if context describes changes in other packages\nor unrelated features, simply ignore it and focus on what actually changed in this release.\n\nInvestigate as needed to write accurate, helpful release notes."
69
+ },
70
+ {
71
+ "role": "assistant",
72
+ "content": null,
73
+ "tool_calls": [
74
+ {
75
+ "id": "call_Bxq23uT1YbTo4p4AX4NSDOSa",
76
+ "type": "function",
77
+ "function": {
78
+ "name": "get_release_stats",
79
+ "arguments": "{\"fromRef\": \"main\", \"toRef\": \"HEAD\"}"
80
+ }
81
+ },
82
+ {
83
+ "id": "call_WhvQhNAmmfcdghJStWWzwuJk",
84
+ "type": "function",
85
+ "function": {
86
+ "name": "analyze_commit_patterns",
87
+ "arguments": "{\"fromRef\": \"main\", \"toRef\": \"HEAD\"}"
88
+ }
89
+ },
90
+ {
91
+ "id": "call_JiLvxE6xYsT3tGBCvS9uYanT",
92
+ "type": "function",
93
+ "function": {
94
+ "name": "get_breaking_changes",
95
+ "arguments": "{\"fromRef\": \"main\", \"toRef\": \"HEAD\"}"
96
+ }
97
+ },
98
+ {
99
+ "id": "call_ZIFy2dkwpQcv7WOnaySQgjWY",
100
+ "type": "function",
101
+ "function": {
102
+ "name": "get_tag_history",
103
+ "arguments": "{\"limit\": 20, \"pattern\": \"v*\"}"
104
+ }
105
+ }
106
+ ]
107
+ },
108
+ {
109
+ "role": "tool",
110
+ "tool_call_id": "call_Bxq23uT1YbTo4p4AX4NSDOSa",
111
+ "content": "Total commits: 13\n\nContributors:\n 10\tTim O'Brien\n 3\tdependabot[bot]\n\n\nFile changes: 5 files changed, 309 insertions(+), 212 deletions(-)\n\nTop 10 most changed files:\n vitest.config.ts | 13 +-\n package.json | 13 +-\n package-lock.json | 489 +++++++++++++++++++--------------\n 5 files changed, 309 insertions(+), 212 deletions(-)\n {src => tests}/tools.test.ts | 2 +-\n {src => tests}/context-manager.test.ts | 4 +-\n",
112
+ "name": "get_release_stats"
113
+ },
114
+ {
115
+ "role": "tool",
116
+ "tool_call_id": "call_WhvQhNAmmfcdghJStWWzwuJk",
117
+ "content": "Commit types:\n chore: 3\n\nTop keywords in commits:\n chore: 3\n merge: 3\n request: 3\n kjerneverk: 3\n dependabot: 3\n npm_and_yarn: 3\n release: 2\n version: 2\n globals: 2\n vitest: 2\n separating: 1\n tests: 1\n making: 1\n coverage: 1\n reports: 1",
118
+ "name": "analyze_commit_patterns"
119
+ },
120
+ {
121
+ "role": "tool",
122
+ "tool_call_id": "call_JiLvxE6xYsT3tGBCvS9uYanT",
123
+ "content": "No obvious breaking changes detected. Manual review recommended for API changes.",
124
+ "name": "get_breaking_changes"
125
+ },
126
+ {
127
+ "role": "tool",
128
+ "tool_call_id": "call_ZIFy2dkwpQcv7WOnaySQgjWY",
129
+ "content": "Recent release tags:\nv0.0.3-dev.0: tag v0.0.3-dev.0\nTagger: Tim O'Brien <tobrien@discursive.com>\n\n0.0.3-dev.0\n2026-01-10 12:23:27 -0800 - 0.0.3-dev.0\nv0.0.2: 2026-01-10 12:10:54 -0800 - chore(release): bump version to 0.0.2 (#4)\nv0.0.2-dev.0: tag v0.0.2-dev.0\nTagger: Tim O'Brien <tobrien@discursive.com>\n\n0.0.2-dev.0\n2026-01-10 11:19:56 -0800 - 0.0.2-dev.0",
130
+ "name": "get_tag_history"
131
+ },
132
+ {
133
+ "role": "assistant",
134
+ "content": null,
135
+ "tool_calls": [
136
+ {
137
+ "id": "call_AhKKrc4f6qTBXI1wNmnPKgTm",
138
+ "type": "function",
139
+ "function": {
140
+ "name": "get_file_content",
141
+ "arguments": "{\"filePath\": \"package.json\"}"
142
+ }
143
+ },
144
+ {
145
+ "id": "call_H00KXudt39I6e2fAT49Eouzx",
146
+ "type": "function",
147
+ "function": {
148
+ "name": "get_file_content",
149
+ "arguments": "{\"filePath\": \"vitest.config.ts\"}"
150
+ }
151
+ },
152
+ {
153
+ "id": "call_75fmWwy1dSdKRO4hVM4Xr9t4",
154
+ "type": "function",
155
+ "function": {
156
+ "name": "search_codebase",
157
+ "arguments": "{\"query\": \"from 'zod'\", \"fileTypes\": [\"ts\", \"js\"], \"contextLines\": 2}"
158
+ }
159
+ },
160
+ {
161
+ "id": "call_KlgT1omj5kFLshIKEaTxPgJh",
162
+ "type": "function",
163
+ "function": {
164
+ "name": "search_codebase",
165
+ "arguments": "{\"query\": \"export .*zod|z\\\\.\", \"fileTypes\": [\"ts\"], \"contextLines\": 2}"
166
+ }
167
+ }
168
+ ]
169
+ },
170
+ {
171
+ "role": "tool",
172
+ "tool_call_id": "call_AhKKrc4f6qTBXI1wNmnPKgTm",
173
+ "content": "{\n \"name\": \"@riotprompt/agentic\",\n \"version\": \"0.0.3\",\n \"description\": \"Shared agentic framework for multi-turn AI conversations and tool orchestration\",\n \"type\": \"module\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n }\n },\n \"scripts\": {\n \"clean\": \"rm -rf dist\",\n \"build\": \"vite build\",\n \"test\": \"vitest run --coverage\",\n \"test:coverage\": \"vitest run --coverage\",\n \"lint\": \"eslint src\",\n \"precommit\": \"npm run lint && npm run test\",\n \"prepublishOnly\": \"npm run clean && npm run build\"\n },\n \"keywords\": [\n \"agentic\",\n \"ai\",\n \"llm\",\n \"conversation\",\n \"tools\",\n \"multi-turn\",\n \"orchestration\"\n ],\n \"author\": \"Tim O'Brien <tobrien@discursive.com>\",\n \"license\": \"Apache-2.0\",\n \"dependencies\": {\n \"zod\": \"^4.3.5\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^25.0.6\",\n \"@typescript-eslint/eslint-plugin\": \"^8.33.1\",\n \"@typescript-eslint/parser\": \"^8.33.1\",\n \"@vitest/coverage-v8\": \"^4.0.16\",\n \"eslint\": \"^9.28.0\",\n \"globals\": \"^17.0.0\",\n \"typescript\": \"^5.8.3\",\n \"vite\": \"^7.0.4\",\n \"vite-plugin-dts\": \"^4.5.4\",\n \"vitest\": \"^4.0.16\"\n }\n}\n",
174
+ "name": "get_file_content"
175
+ },
176
+ {
177
+ "role": "tool",
178
+ "tool_call_id": "call_H00KXudt39I6e2fAT49Eouzx",
179
+ "content": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n test: {\n include: [\"tests/**/*.test.ts\"],\n globals: true,\n coverage: {\n provider: \"v8\",\n reporter: [\"text\", \"json\", \"html\"],\n include: [\"src/**/*.ts\"],\n exclude: [\n \"src/**/*.test.ts\",\n \"node_modules/\",\n \"dist/**\",\n \"vitest.config.ts\",\n \"vite.config.ts\",\n \"eslint.config.mjs\",\n ],\n },\n },\n});\n\n",
180
+ "name": "get_file_content"
181
+ },
182
+ {
183
+ "role": "tool",
184
+ "tool_call_id": "call_75fmWwy1dSdKRO4hVM4Xr9t4",
185
+ "content": "src/tools.ts-5- */\nsrc/tools.ts-6-\nsrc/tools.ts:7:import { z } from 'zod';\nsrc/tools.ts-8-import { DEFAULT_LOGGER, wrapLogger, type Logger } from './logger';\nsrc/tools.ts-9-\n",
186
+ "name": "search_codebase"
187
+ },
188
+ {
189
+ "role": "tool",
190
+ "tool_call_id": "call_KlgT1omj5kFLshIKEaTxPgJh",
191
+ "content": "Tool execution failed: Tool \"search_codebase\" execution failed: Search failed: Command failed: git grep -n -C 2 \"export .*zod|z\\.\" -- '*.ts'\n",
192
+ "name": "search_codebase"
193
+ },
194
+ {
195
+ "role": "assistant",
196
+ "content": null,
197
+ "tool_calls": [
198
+ {
199
+ "id": "call_jDyZhFnWgcbTL2fkQKXafgqA",
200
+ "type": "function",
201
+ "function": {
202
+ "name": "search_codebase",
203
+ "arguments": "{\"query\": \"zod\", \"fileTypes\": [\"ts\"], \"contextLines\": 2}"
204
+ }
205
+ },
206
+ {
207
+ "id": "call_WicxFOsjmhuL62thhbeNQGJ7",
208
+ "type": "function",
209
+ "function": {
210
+ "name": "get_file_content",
211
+ "arguments": "{\"filePath\": \"src/index.ts\", \"includeLineNumbers\": true}"
212
+ }
213
+ },
214
+ {
215
+ "id": "call_0HlRHyfUvMeLlu8PkIVdvLsN",
216
+ "type": "function",
217
+ "function": {
218
+ "name": "get_file_content",
219
+ "arguments": "{\"filePath\": \"src/tools.ts\", \"includeLineNumbers\": true}"
220
+ }
221
+ },
222
+ {
223
+ "id": "call_wWwLDvCqIS02hx5AKmL8Pewu",
224
+ "type": "function",
225
+ "function": {
226
+ "name": "get_file_content",
227
+ "arguments": "{\"filePath\": \"src/context-manager.ts\", \"includeLineNumbers\": true}"
228
+ }
229
+ }
230
+ ]
231
+ },
232
+ {
233
+ "role": "tool",
234
+ "tool_call_id": "call_jDyZhFnWgcbTL2fkQKXafgqA",
235
+ "content": "src/tools.ts-5- */\nsrc/tools.ts-6-\nsrc/tools.ts:7:import { z } from 'zod';\nsrc/tools.ts-8-import { DEFAULT_LOGGER, wrapLogger, type Logger } from './logger';\nsrc/tools.ts-9-\n--\nvite.config.ts-12- },\nvite.config.ts-13- rollupOptions: {\nvite.config.ts:14: external: [\"zod\", \"execution\"],\nvite.config.ts-15- },\nvite.config.ts-16- sourcemap: true,\n",
236
+ "name": "search_codebase"
237
+ },
238
+ {
239
+ "role": "tool",
240
+ "tool_call_id": "call_WicxFOsjmhuL62thhbeNQGJ7",
241
+ "content": "1: /**\n2: * Agentic Package\n3: *\n4: * Components for building agentic AI workflows:\n5: * - Tool registry and execution\n6: * - Context management\n7: * - Conversation state tracking\n8: *\n9: * @packageDocumentation\n10: */\n11: \n12: // Types\n13: export type {\n14: ConversationMessage,\n15: ToolCall,\n16: Model,\n17: ToolUsagePolicy,\n18: IterationAction,\n19: ToolCallAction,\n20: InjectOptions,\n21: DynamicContentItem,\n22: TrackedContextItem,\n23: LLMClient,\n24: StrategyState,\n25: Insight,\n26: ToolResult,\n27: PhaseResult,\n28: TokenUsage,\n29: CompressionStats,\n30: CompressionStrategy,\n31: TokenBudgetConfig,\n32: LogFormat,\n33: LogConfig,\n34: } from './types';\n35: \n36: // Logger\n37: export type { Logger } from './logger';\n38: export { DEFAULT_LOGGER, wrapLogger, LIBRARY_NAME } from './logger';\n39: \n40: // Tool Registry\n41: export type {\n42: ToolParameter,\n43: ToolContext,\n44: ToolExample,\n45: ToolCost,\n46: Tool,\n47: OpenAITool,\n48: AnthropicTool,\n49: ToolExecutionResult,\n50: ToolUsageStats,\n51: ToolDefinition,\n52: } from './tools';\n53: export { ToolRegistry } from './tools';\n54: \n55: // Context Manager\n56: export type { ContextStats } from './context-manager';\n57: export { ContextManager } from './context-manager';\n58: \n59: /**\n60: * Package version\n61: */\n62: export const VERSION = '0.0.1';\n63: ",
242
+ "name": "get_file_content"
243
+ },
244
+ {
245
+ "role": "tool",
246
+ "tool_call_id": "call_0HlRHyfUvMeLlu8PkIVdvLsN",
247
+ "content": "1: /**\n2: * Agentic Package - Tool Registry\n3: *\n4: * Manages tool definitions and execution for agentic workflows.\n5: */\n6: \n7: import { z } from 'zod';\n8: import { DEFAULT_LOGGER, wrapLogger, type Logger } from './logger';\n9: \n10: // ===== TYPE DEFINITIONS =====\n11: \n12: /**\n13: * Parameter definition for a tool\n14: */\n15: export interface ToolParameter {\n16: type: 'string' | 'number' | 'boolean' | 'array' | 'object';\n17: description: string;\n18: items?: ToolParameter;\n19: properties?: Record<string, ToolParameter>;\n20: required?: string[];\n21: enum?: string[];\n22: default?: any;\n23: }\n24: \n25: /**\n26: * Context provided to tool execution\n27: */\n28: export interface ToolContext {\n29: workingDirectory?: string;\n30: storage?: any;\n31: logger?: Logger;\n32: conversationState?: any;\n33: [key: string]: any;\n34: }\n35: \n36: /**\n37: * Example usage of a tool\n38: */\n39: export interface ToolExample {\n40: scenario: string;\n41: params: any;\n42: expectedResult: string;\n43: }\n44: \n45: /**\n46: * Cost hint for tool execution\n47: */\n48: export type ToolCost = 'cheap' | 'moderate' | 'expensive';\n49: \n50: /**\n51: * Tool definition\n52: */\n53: export interface Tool {\n54: name: string;\n55: description: string;\n56: parameters: {\n57: type: 'object';\n58: properties: Record<string, ToolParameter>;\n59: required?: string[];\n60: };\n61: execute: (params: any, context?: ToolContext) => Promise<any>;\n62: category?: string;\n63: cost?: ToolCost;\n64: examples?: ToolExample[];\n65: }\n66: \n67: /**\n68: * OpenAI-compatible tool format\n69: */\n70: export interface OpenAITool {\n71: type: 'function';\n72: function: {\n73: name: string;\n74: description: string;\n75: parameters: {\n76: type: 'object';\n77: properties: Record<string, any>;\n78: required?: string[];\n79: };\n80: };\n81: }\n82: \n83: /**\n84: * Anthropic-compatible tool format\n85: */\n86: export interface AnthropicTool {\n87: name: string;\n88: description: string;\n89: input_schema: {\n90: type: 'object';\n91: properties: Record<string, any>;\n92: required?: string[];\n93: };\n94: }\n95: \n96: /**\n97: * Tool execution result\n98: */\n99: export interface ToolExecutionResult {\n100: success: boolean;\n101: result?: any;\n102: error?: string;\n103: duration?: number;\n104: }\n105: \n106: /**\n107: * Usage statistics for a tool\n108: */\n109: export interface ToolUsageStats {\n110: calls: number;\n111: failures: number;\n112: successRate: number;\n113: averageDuration?: number;\n114: }\n115: \n116: /**\n117: * Tool definition for export\n118: */\n119: export interface ToolDefinition {\n120: name: string;\n121: description: string;\n122: parameters: Tool['parameters'];\n123: category?: string;\n124: cost?: ToolCost;\n125: examples?: ToolExample[];\n126: }\n127: \n128: // ===== VALIDATION SCHEMAS =====\n129: \n130: const ToolSchema = z\n131: .object({\n132: name: z.string().min(1),\n133: description: z.string().min(1),\n134: parameters: z\n135: .object({\n136: type: z.literal('object'),\n137: properties: z.record(z.string(), z.any()).default({}),\n138: required: z.array(z.string()).optional(),\n139: })\n140: .passthrough(),\n141: execute: z.custom<(params: any, context?: any) => Promise<any>>(\n142: (val) => typeof val === 'function',\n143: { message: 'execute must be a function' }\n144: ),\n145: category: z.string().optional(),\n146: cost: z.enum(['cheap', 'moderate', 'expensive']).optional(),\n147: examples: z\n148: .array(\n149: z.object({\n150: scenario: z.string(),\n151: params: z.any(),\n152: expectedResult: z.string(),\n153: })\n154: )\n155: .optional(),\n156: })\n157: .passthrough();\n158: \n159: // ===== TOOL REGISTRY =====\n160: \n161: /**\n162: * ToolRegistry manages tool definitions and execution.\n163: */\n164: export class ToolRegistry {\n165: private tools: Map<string, Tool>;\n166: private context: ToolContext;\n167: private logger: Logger;\n168: private usageStats: Map<\n169: string,\n170: { calls: number; failures: number; totalDuration: number }\n171: >;\n172: \n173: private constructor(context: ToolContext = {}, logger?: Logger) {\n174: this.tools = new Map();\n175: this.context = context;\n176: this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ToolRegistry');\n177: this.usageStats = new Map();\n178: \n179: this.logger.debug('Created ToolRegistry');\n180: }\n181: \n182: /**\n183: * Create a new ToolRegistry instance\n184: */\n185: static create(context?: ToolContext, logger?: Logger): ToolRegistry {\n186: return new ToolRegistry(context, logger);\n187: }\n188: \n189: /**\n190: * Register a single tool\n191: */\n192: register(tool: Tool): void {\n193: try {\n194: ToolSchema.parse(tool);\n195: } catch (error) {\n196: throw new Error(`Invalid tool definition for \"${tool.name}\": ${error}`);\n197: }\n198: \n199: if (this.tools.has(tool.name)) {\n200: this.logger.warn(`Tool \"${tool.name}\" already registered, overwriting`);\n201: }\n202: \n203: this.tools.set(tool.name, tool);\n204: this.usageStats.set(tool.name, { calls: 0, failures: 0, totalDuration: 0 });\n205: \n206: this.logger.debug('Registered tool', {\n207: name: tool.name,\n208: category: tool.category,\n209: });\n210: }\n211: \n212: /**\n213: * Register multiple tools at once\n214: */\n215: registerAll(tools: Tool[]): void {\n216: this.logger.debug('Registering multiple tools', { count: tools.length });\n217: tools.forEach((tool) => this.register(tool));\n218: }\n219: \n220: /**\n221: * Get a tool by name\n222: */\n223: get(name: string): Tool | undefined {\n224: return this.tools.get(name);\n225: }\n226: \n227: /**\n228: * Get all registered tools\n229: */\n230: getAll(): Tool[] {\n231: return Array.from(this.tools.values());\n232: }\n233: \n234: /**\n235: * Get tools by category\n236: */\n237: getByCategory(category: string): Tool[] {\n238: return this.getAll().filter((tool) => tool.category === category);\n239: }\n240: \n241: /**\n242: * Check if a tool is registered\n243: */\n244: has(name: string): boolean {\n245: return this.tools.has(name);\n246: }\n247: \n248: /**\n249: * Get number of registered tools\n250: */\n251: count(): number {\n252: return this.tools.size;\n253: }\n254: \n255: /**\n256: * Execute a tool by name\n257: */\n258: async execute(name: string, params: any): Promise<any> {\n259: const tool = this.tools.get(name);\n260: \n261: if (!tool) {\n262: throw new Error(`Tool \"${name}\" not found`);\n263: }\n264: \n265: this.logger.debug('Executing tool', { name, params });\n266: \n267: const startTime = Date.now();\n268: const stats = this.usageStats.get(name)!;\n269: stats.calls++;\n270: \n271: try {\n272: const result = await tool.execute(params, this.context);\n273: \n274: const duration = Date.now() - startTime;\n275: stats.totalDuration += duration;\n276: \n277: this.logger.debug('Tool execution succeeded', { name, duration });\n278: \n279: return result;\n280: } catch (error) {\n281: stats.failures++;\n282: \n283: this.logger.error('Tool execution failed', { name, error });\n284: \n285: throw error;\n286: }\n287: }\n288: \n289: /**\n290: * Execute multiple tools in sequence\n291: */\n292: async executeBatch(\n293: calls: Array<{ name: string; params: any }>\n294: ): Promise<any[]> {\n295: this.logger.debug('Executing batch', { count: calls.length });\n296: \n297: const results: any[] = [];\n298: \n299: for (const call of calls) {\n300: try {\n301: const result = await this.execute(call.name, call.params);\n302: results.push(result);\n303: } catch (error) {\n304: results.push({ error: String(error) });\n305: }\n306: }\n307: \n308: return results;\n309: }\n310: \n311: /**\n312: * Export tools in OpenAI format\n313: */\n314: toOpenAIFormat(): OpenAITool[] {\n315: return this.getAll().map((tool) => ({\n316: type: 'function' as const,\n317: function: {\n318: name: tool.name,\n319: description: tool.description,\n320: parameters: {\n321: type: 'object' as const,\n322: properties: tool.parameters.properties,\n323: required: tool.parameters.required,\n324: },\n325: },\n326: }));\n327: }\n328: \n329: /**\n330: * Export tools in Anthropic format\n331: */\n332: toAnthropicFormat(): AnthropicTool[] {\n333: return this.getAll().map((tool) => ({\n334: name: tool.name,\n335: description: tool.description,\n336: input_schema: {\n337: type: 'object' as const,\n338: properties: tool.parameters.properties,\n339: required: tool.parameters.required,\n340: },\n341: }));\n342: }\n343: \n344: /**\n345: * Get tool definitions (without execute function)\n346: */\n347: getDefinitions(): ToolDefinition[] {\n348: return this.getAll().map((tool) => ({\n349: name: tool.name,\n350: description: tool.description,\n351: parameters: tool.parameters,\n352: category: tool.category,\n353: cost: tool.cost,\n354: examples: tool.examples,\n355: }));\n356: }\n357: \n358: /**\n359: * Get usage statistics for all tools\n360: */\n361: getUsageStats(): Map<string, ToolUsageStats> {\n362: const stats = new Map<string, ToolUsageStats>();\n363: \n364: this.usageStats.forEach((rawStats, name) => {\n365: stats.set(name, {\n366: calls: rawStats.calls,\n367: failures: rawStats.failures,\n368: successRate:\n369: rawStats.calls > 0\n370: ? (rawStats.calls - rawStats.failures) / rawStats.calls\n371: : 0,\n372: averageDuration:\n373: rawStats.calls > 0\n374: ? rawStats.totalDuration / rawStats.calls\n375: : undefined,\n376: });\n377: });\n378: \n379: return stats;\n380: }\n381: \n382: /**\n383: * Get most frequently used tools\n384: */\n385: getMostUsed(limit: number = 5): Tool[] {\n386: const sorted = Array.from(this.usageStats.entries())\n387: .sort((a, b) => b[1].calls - a[1].calls)\n388: .slice(0, limit)\n389: .map(([name]) => this.tools.get(name)!)\n390: .filter((tool) => tool !== undefined);\n391: \n392: return sorted;\n393: }\n394: \n395: /**\n396: * Get list of all categories\n397: */\n398: getCategories(): string[] {\n399: const categories = new Set<string>();\n400: \n401: this.getAll().forEach((tool) => {\n402: if (tool.category) {\n403: categories.add(tool.category);\n404: }\n405: });\n406: \n407: return Array.from(categories).sort();\n408: }\n409: \n410: /**\n411: * Update execution context\n412: */\n413: updateContext(context: Partial<ToolContext>): void {\n414: this.context = { ...this.context, ...context };\n415: this.logger.debug('Updated context', { keys: Object.keys(context) });\n416: }\n417: \n418: /**\n419: * Get current context\n420: */\n421: getContext(): ToolContext {\n422: return { ...this.context };\n423: }\n424: \n425: /**\n426: * Clear all tools\n427: */\n428: clear(): void {\n429: this.logger.debug('Clearing all tools');\n430: this.tools.clear();\n431: this.usageStats.clear();\n432: }\n433: \n434: /**\n435: * Unregister a specific tool\n436: */\n437: unregister(name: string): boolean {\n438: if (this.tools.has(name)) {\n439: this.tools.delete(name);\n440: this.usageStats.delete(name);\n441: this.logger.debug('Unregistered tool', { name });\n442: return true;\n443: }\n444: \n445: return false;\n446: }\n447: \n448: /**\n449: * Reset usage statistics\n450: */\n451: resetStats(): void {\n452: this.logger.debug('Resetting usage statistics');\n453: \n454: this.usageStats.forEach((stats) => {\n455: stats.calls = 0;\n456: stats.failures = 0;\n457: stats.totalDuration = 0;\n458: });\n459: }\n460: }\n461: \n462: export default ToolRegistry;\n463: \n464: ",
248
+ "name": "get_file_content"
249
+ },
250
+ {
251
+ "role": "tool",
252
+ "tool_call_id": "call_wWwLDvCqIS02hx5AKmL8Pewu",
253
+ "content": "1: /**\n2: * Agentic Package - Context Manager\n3: *\n4: * Tracks and manages dynamically injected context in conversations.\n5: */\n6: \n7: import crypto from 'crypto';\n8: import { DEFAULT_LOGGER, wrapLogger, type Logger } from './logger';\n9: import type { DynamicContentItem, TrackedContextItem } from './types';\n10: \n11: /**\n12: * Context statistics\n13: */\n14: export interface ContextStats {\n15: totalItems: number;\n16: byCategory: Map<string, number>;\n17: byPriority: Map<string, number>;\n18: bySource: Map<string, number>;\n19: oldestTimestamp?: Date;\n20: newestTimestamp?: Date;\n21: }\n22: \n23: /**\n24: * ContextManager tracks and manages dynamically injected context.\n25: */\n26: export class ContextManager {\n27: private items: Map<string, TrackedContextItem>;\n28: private hashes: Set<string>;\n29: private logger: Logger;\n30: \n31: constructor(logger?: Logger) {\n32: this.items = new Map();\n33: this.hashes = new Set();\n34: this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ContextManager');\n35: }\n36: \n37: /**\n38: * Track a context item\n39: */\n40: track(item: DynamicContentItem, position: number): void {\n41: const hash = this.hashContent(item.content);\n42: \n43: if (!item.id && this.hashes.has(hash)) {\n44: this.logger.debug('Skipping duplicate context item by hash', { hash });\n45: return;\n46: }\n47: \n48: const id = item.id || this.generateId();\n49: \n50: const trackedItem: TrackedContextItem = {\n51: ...item,\n52: id,\n53: hash,\n54: position,\n55: injectedAt: new Date(),\n56: timestamp: item.timestamp || new Date(),\n57: priority: item.priority || 'medium',\n58: };\n59: \n60: this.items.set(id, trackedItem);\n61: this.hashes.add(hash);\n62: \n63: this.logger.debug('Tracked context item', {\n64: id,\n65: category: item.category,\n66: position,\n67: });\n68: }\n69: \n70: /**\n71: * Check if context with given ID exists\n72: */\n73: hasContext(id: string): boolean {\n74: return this.items.has(id);\n75: }\n76: \n77: /**\n78: * Check if content with given hash exists\n79: */\n80: hasContentHash(content: string): boolean {\n81: const hash = this.hashContent(content);\n82: return this.hashes.has(hash);\n83: }\n84: \n85: /**\n86: * Check if similar content exists (fuzzy match)\n87: */\n88: hasSimilarContent(\n89: content: string,\n90: similarityThreshold: number = 0.9\n91: ): boolean {\n92: const MAX_ITEMS_WARNING = 1000;\n93: if (this.items.size > MAX_ITEMS_WARNING) {\n94: this.logger.warn(\n95: 'Large number of context items, similarity check may be slow',\n96: {\n97: count: this.items.size,\n98: threshold: MAX_ITEMS_WARNING,\n99: }\n100: );\n101: }\n102: \n103: const normalized = this.normalizeContent(content);\n104: \n105: for (const item of this.items.values()) {\n106: const itemNormalized = this.normalizeContent(item.content || '');\n107: \n108: if (normalized === itemNormalized) {\n109: return true;\n110: }\n111: \n112: const longer =\n113: normalized.length > itemNormalized.length\n114: ? normalized\n115: : itemNormalized;\n116: const shorter =\n117: normalized.length <= itemNormalized.length\n118: ? normalized\n119: : itemNormalized;\n120: \n121: const lengthRatio = shorter.length / longer.length;\n122: \n123: if (lengthRatio >= similarityThreshold) {\n124: if (longer.includes(shorter)) {\n125: return true;\n126: }\n127: }\n128: }\n129: \n130: return false;\n131: }\n132: \n133: /**\n134: * Get context item by ID\n135: */\n136: get(id: string): TrackedContextItem | undefined {\n137: return this.items.get(id);\n138: }\n139: \n140: /**\n141: * Get all tracked context items\n142: */\n143: getAll(): TrackedContextItem[] {\n144: return Array.from(this.items.values());\n145: }\n146: \n147: /**\n148: * Get context items by category\n149: */\n150: getByCategory(category: string): TrackedContextItem[] {\n151: return this.getAll().filter((item) => item.category === category);\n152: }\n153: \n154: /**\n155: * Get context items by priority\n156: */\n157: getByPriority(priority: 'high' | 'medium' | 'low'): TrackedContextItem[] {\n158: return this.getAll().filter((item) => item.priority === priority);\n159: }\n160: \n161: /**\n162: * Get context items by source\n163: */\n164: getBySource(source: string): TrackedContextItem[] {\n165: return this.getAll().filter((item) => item.source === source);\n166: }\n167: \n168: /**\n169: * Get all categories\n170: */\n171: getCategories(): string[] {\n172: const categories = new Set<string>();\n173: this.items.forEach((item) => {\n174: if (item.category) {\n175: categories.add(item.category);\n176: }\n177: });\n178: return Array.from(categories).sort();\n179: }\n180: \n181: /**\n182: * Get context statistics\n183: */\n184: getStats(): ContextStats {\n185: const byCategory = new Map<string, number>();\n186: const byPriority = new Map<string, number>();\n187: const bySource = new Map<string, number>();\n188: let oldestTimestamp: Date | undefined;\n189: let newestTimestamp: Date | undefined;\n190: \n191: this.items.forEach((item) => {\n192: if (item.category) {\n193: byCategory.set(\n194: item.category,\n195: (byCategory.get(item.category) || 0) + 1\n196: );\n197: }\n198: \n199: const priority = item.priority || 'medium';\n200: byPriority.set(priority, (byPriority.get(priority) || 0) + 1);\n201: \n202: if (item.source) {\n203: bySource.set(item.source, (bySource.get(item.source) || 0) + 1);\n204: }\n205: \n206: if (item.timestamp) {\n207: if (!oldestTimestamp || item.timestamp < oldestTimestamp) {\n208: oldestTimestamp = item.timestamp;\n209: }\n210: if (!newestTimestamp || item.timestamp > newestTimestamp) {\n211: newestTimestamp = item.timestamp;\n212: }\n213: }\n214: });\n215: \n216: return {\n217: totalItems: this.items.size,\n218: byCategory,\n219: byPriority,\n220: bySource,\n221: oldestTimestamp,\n222: newestTimestamp,\n223: };\n224: }\n225: \n226: /**\n227: * Remove context item by ID\n228: */\n229: remove(id: string): boolean {\n230: const item = this.items.get(id);\n231: if (item) {\n232: this.items.delete(id);\n233: this.hashes.delete(item.hash);\n234: this.logger.debug('Removed context item', { id });\n235: return true;\n236: }\n237: return false;\n238: }\n239: \n240: /**\n241: * Clear all tracked context\n242: */\n243: clear(): void {\n244: this.items.clear();\n245: this.hashes.clear();\n246: this.logger.debug('Cleared all context');\n247: }\n248: \n249: private generateId(): string {\n250: return `ctx-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n251: }\n252: \n253: private hashContent(content: string): string {\n254: return crypto\n255: .createHash('sha256')\n256: .update(content)\n257: .digest('hex')\n258: .substring(0, 16);\n259: }\n260: \n261: private normalizeContent(content: string): string {\n262: return content.replace(/\\s+/g, ' ').trim().toLowerCase();\n263: }\n264: }\n265: \n266: export default ContextManager;\n267: \n268: ",
254
+ "name": "get_file_content"
255
+ },
256
+ {
257
+ "role": "assistant",
258
+ "content": "RELEASE_NOTES:\n{\n \"title\": \"@riotprompt/agentic v0.0.3 — test/coverage workflow improvements + dependency updates\",\n \"body\": \"## Summary\\nThis release is primarily about improving the project’s test setup and CI ergonomics (separating tests from `src/`, generating coverage by default), plus routine dependency updates.\\n\\nNo production source files changed in this range; the runtime/public API is expected to be unchanged.\\n\\n## What changed\\n### Testing & coverage\\n- **Tests moved out of `src/` into `tests/`**\\n - `src/context-manager.test.ts` → `tests/context-manager.test.ts`\\n - `src/tools.test.ts` → `tests/tools.test.ts`\\n - Imports were updated to reference `../src/...`.\\n - **Why it matters:** keeps the production source tree clean and avoids test files being treated like library source (e.g., during packaging/type generation).\\n\\n- **Coverage is now generated by default when running tests**\\n - `npm test` now runs: `vitest run --coverage`\\n - Added explicit alias: `npm run test:coverage`\\n - Coverage reporting now includes **text, JSON, and HTML**.\\n - Coverage config excludes common non-source inputs (`dist/**`, config files, etc.) to reduce noise.\\n - **Why it matters:** makes it easier to enforce and consume coverage in CI and to inspect results locally.\\n\\n### Developer workflow\\n- Added a `precommit` script:\\n - `npm run precommit` → runs `lint` then `test`\\n - **Note:** this adds a convenient entry point, but does not itself install a git hook (that would require additional tooling/config).\\n\\n### Dependency updates\\n- **zod** upgraded from `^3.25.51` → `^4.3.5`\\n- **vitest** upgraded from `^3.2.4` → `^4.0.16`\\n- Added **@vitest/coverage-v8** `^4.0.16` to support v8 coverage reporting\\n- **globals** upgraded from `^16.2.0` → `^17.0.0`\\n- `package-lock.json` updated accordingly\\n\\n## Impact\\n### For library consumers\\n- No expected behavior/API changes in the exported library surface.\\n- Indirect impact: the package now depends on **Zod v4**. Most consumers won’t notice, but if your tooling forces dependency deduping/resolutions, ensure your Zod constraints are compatible.\\n\\n### For contributors/maintainers\\n- `npm test` is now **slower** (coverage collection is enabled by default) but produces coverage artifacts/reports.\\n- Tests must live under `tests/**/*.test.ts` to be picked up by the current Vitest config.\\n\\n## Breaking changes\\n- No explicit breaking changes detected in code or exports.\\n- Potential workflow break for contributors: if you had tests under `src/**/*.test.ts`, they will **no longer run** unless moved under `tests/` (or the Vitest include pattern is adjusted).\\n\"\n}"
259
+ }
260
+ ]
261
+ ```
262
+
263
+ </details>
264
+
265
+ ## Generated Release Notes
266
+
267
+ ### Title
268
+ ```
269
+ @riotprompt/agentic v0.0.3 — test/coverage workflow improvements + dependency updates
270
+ ```
271
+
272
+ ### Body
273
+ ```markdown
274
+ ## Summary
275
+ This release is primarily about improving the project’s test setup and CI ergonomics (separating tests from `src/`, generating coverage by default), plus routine dependency updates.
276
+
277
+ No production source files changed in this range; the runtime/public API is expected to be unchanged.
278
+
279
+ ## What changed
280
+ ### Testing & coverage
281
+ - **Tests moved out of `src/` into `tests/`**
282
+ - `src/context-manager.test.ts` → `tests/context-manager.test.ts`
283
+ - `src/tools.test.ts` → `tests/tools.test.ts`
284
+ - Imports were updated to reference `../src/...`.
285
+ - **Why it matters:** keeps the production source tree clean and avoids test files being treated like library source (e.g., during packaging/type generation).
286
+
287
+ - **Coverage is now generated by default when running tests**
288
+ - `npm test` now runs: `vitest run --coverage`
289
+ - Added explicit alias: `npm run test:coverage`
290
+ - Coverage reporting now includes **text, JSON, and HTML**.
291
+ - Coverage config excludes common non-source inputs (`dist/**`, config files, etc.) to reduce noise.
292
+ - **Why it matters:** makes it easier to enforce and consume coverage in CI and to inspect results locally.
293
+
294
+ ### Developer workflow
295
+ - Added a `precommit` script:
296
+ - `npm run precommit` → runs `lint` then `test`
297
+ - **Note:** this adds a convenient entry point, but does not itself install a git hook (that would require additional tooling/config).
298
+
299
+ ### Dependency updates
300
+ - **zod** upgraded from `^3.25.51` → `^4.3.5`
301
+ - **vitest** upgraded from `^3.2.4` → `^4.0.16`
302
+ - Added **@vitest/coverage-v8** `^4.0.16` to support v8 coverage reporting
303
+ - **globals** upgraded from `^16.2.0` → `^17.0.0`
304
+ - `package-lock.json` updated accordingly
305
+
306
+ ## Impact
307
+ ### For library consumers
308
+ - No expected behavior/API changes in the exported library surface.
309
+ - Indirect impact: the package now depends on **Zod v4**. Most consumers won’t notice, but if your tooling forces dependency deduping/resolutions, ensure your Zod constraints are compatible.
310
+
311
+ ### For contributors/maintainers
312
+ - `npm test` is now **slower** (coverage collection is enabled by default) but produces coverage artifacts/reports.
313
+ - Tests must live under `tests/**/*.test.ts` to be picked up by the current Vitest config.
314
+
315
+ ## Breaking changes
316
+ - No explicit breaking changes detected in code or exports.
317
+ - Potential workflow break for contributors: if you had tests under `src/**/*.test.ts`, they will **no longer run** unless moved under `tests/` (or the Vitest include pattern is adjusted).
318
+
319
+ ```