specsmith 0.3.0.dev138__tar.gz → 0.3.0.dev139__tar.gz

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 (158) hide show
  1. {specsmith-0.3.0.dev138/src/specsmith.egg-info → specsmith-0.3.0.dev139}/PKG-INFO +1 -1
  2. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/pyproject.toml +1 -1
  3. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/runner.py +70 -17
  4. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/cli.py +9 -23
  5. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139/src/specsmith.egg-info}/PKG-INFO +1 -1
  6. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/LICENSE +0 -0
  7. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/README.md +0 -0
  8. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/setup.cfg +0 -0
  9. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/epistemic/__init__.py +0 -0
  10. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/epistemic/belief.py +0 -0
  11. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/epistemic/certainty.py +0 -0
  12. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/epistemic/failure_graph.py +0 -0
  13. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/epistemic/py.typed +0 -0
  14. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/epistemic/recovery.py +0 -0
  15. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/epistemic/session.py +0 -0
  16. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/epistemic/stress_tester.py +0 -0
  17. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/epistemic/trace.py +0 -0
  18. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/__init__.py +0 -0
  19. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/__main__.py +0 -0
  20. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/__init__.py +0 -0
  21. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/core.py +0 -0
  22. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/hooks.py +0 -0
  23. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/optimizer.py +0 -0
  24. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/profiles/epistemic-auditor.md +0 -0
  25. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/profiles/planner.md +0 -0
  26. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/profiles/verifier.md +0 -0
  27. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/providers/__init__.py +0 -0
  28. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/providers/anthropic.py +0 -0
  29. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/providers/gemini.py +0 -0
  30. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/providers/mistral.py +0 -0
  31. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/providers/ollama.py +0 -0
  32. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/providers/openai.py +0 -0
  33. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/skills.py +0 -0
  34. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/agent/tools.py +0 -0
  35. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/architect.py +0 -0
  36. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/auditor.py +0 -0
  37. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/auth.py +0 -0
  38. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/commands/__init__.py +0 -0
  39. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/compressor.py +0 -0
  40. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/config.py +0 -0
  41. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/credit_analyzer.py +0 -0
  42. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/credits.py +0 -0
  43. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/differ.py +0 -0
  44. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/doctor.py +0 -0
  45. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/epistemic/__init__.py +0 -0
  46. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/epistemic/belief.py +0 -0
  47. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/epistemic/certainty.py +0 -0
  48. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/epistemic/failure_graph.py +0 -0
  49. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/epistemic/recovery.py +0 -0
  50. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/epistemic/stress_tester.py +0 -0
  51. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/executor.py +0 -0
  52. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/exporter.py +0 -0
  53. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/gui/__init__.py +0 -0
  54. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/gui/app.py +0 -0
  55. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/gui/main_window.py +0 -0
  56. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/gui/session_tab.py +0 -0
  57. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/gui/theme.py +0 -0
  58. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/gui/widgets/__init__.py +0 -0
  59. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/gui/widgets/chat_view.py +0 -0
  60. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/gui/widgets/input_bar.py +0 -0
  61. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/gui/widgets/provider_bar.py +0 -0
  62. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/gui/widgets/token_meter.py +0 -0
  63. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/gui/widgets/tool_panel.py +0 -0
  64. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/gui/widgets/update_checker.py +0 -0
  65. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/gui/worker.py +0 -0
  66. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/importer.py +0 -0
  67. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/integrations/__init__.py +0 -0
  68. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/integrations/aider.py +0 -0
  69. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/integrations/base.py +0 -0
  70. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/integrations/claude_code.py +0 -0
  71. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/integrations/copilot.py +0 -0
  72. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/integrations/cursor.py +0 -0
  73. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/integrations/gemini.py +0 -0
  74. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/integrations/warp.py +0 -0
  75. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/integrations/windsurf.py +0 -0
  76. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/ledger.py +0 -0
  77. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/patent.py +0 -0
  78. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/plugins.py +0 -0
  79. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/rate_limits.py +0 -0
  80. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/releaser.py +0 -0
  81. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/requirements.py +0 -0
  82. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/scaffolder.py +0 -0
  83. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/session.py +0 -0
  84. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/agents.md.j2 +0 -0
  85. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
  86. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
  87. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/community/contributing.md.j2 +0 -0
  88. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
  89. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
  90. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/community/license-MIT.j2 +0 -0
  91. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
  92. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/community/security.md.j2 +0 -0
  93. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
  94. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
  95. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
  96. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
  97. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
  98. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/docs/workflow.md.j2 +0 -0
  99. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/editorconfig.j2 +0 -0
  100. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/gitattributes.j2 +0 -0
  101. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/gitignore.j2 +0 -0
  102. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/go/go.mod.j2 +0 -0
  103. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/go/main.go.j2 +0 -0
  104. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
  105. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
  106. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
  107. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
  108. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
  109. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/governance/roles.md.j2 +0 -0
  110. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/governance/rules.md.j2 +0 -0
  111. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
  112. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/governance/verification.md.j2 +0 -0
  113. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/governance/workflow.md.j2 +0 -0
  114. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/js/package.json.j2 +0 -0
  115. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/ledger.md.j2 +0 -0
  116. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/python/cli.py.j2 +0 -0
  117. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/python/init.py.j2 +0 -0
  118. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
  119. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/readme.md.j2 +0 -0
  120. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
  121. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/rust/main.rs.j2 +0 -0
  122. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
  123. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
  124. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
  125. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
  126. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
  127. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
  128. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
  129. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/tools.py +0 -0
  130. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/trace.py +0 -0
  131. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/updater.py +0 -0
  132. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/upgrader.py +0 -0
  133. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/validator.py +0 -0
  134. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/vcs/__init__.py +0 -0
  135. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/vcs/base.py +0 -0
  136. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/vcs/bitbucket.py +0 -0
  137. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/vcs/github.py +0 -0
  138. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/vcs/gitlab.py +0 -0
  139. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/vcs_commands.py +0 -0
  140. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith/workspace.py +0 -0
  141. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith.egg-info/SOURCES.txt +0 -0
  142. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith.egg-info/dependency_links.txt +0 -0
  143. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith.egg-info/entry_points.txt +0 -0
  144. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith.egg-info/requires.txt +0 -0
  145. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/src/specsmith.egg-info/top_level.txt +0 -0
  146. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/tests/test_auditor.py +0 -0
  147. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/tests/test_cli.py +0 -0
  148. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/tests/test_compressor.py +0 -0
  149. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/tests/test_epistemic.py +0 -0
  150. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/tests/test_importer.py +0 -0
  151. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/tests/test_integrations.py +0 -0
  152. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/tests/test_optimizer.py +0 -0
  153. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/tests/test_rate_limits.py +0 -0
  154. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/tests/test_scaffolder.py +0 -0
  155. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/tests/test_smoke.py +0 -0
  156. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/tests/test_tools.py +0 -0
  157. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/tests/test_validator.py +0 -0
  158. {specsmith-0.3.0.dev138 → specsmith-0.3.0.dev139}/tests/test_vcs.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specsmith
3
- Version: 0.3.0.dev138
3
+ Version: 0.3.0.dev139
4
4
  Summary: Applied Epistemic Engineering toolkit — forge epistemically-governed scaffolds, stress-test belief systems, and run AEE pipelines.
5
5
  Author: BitConcepts
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "specsmith"
7
- version = "0.3.0.dev138"
7
+ version = "0.3.0.dev139"
8
8
  description = "Applied Epistemic Engineering toolkit — forge epistemically-governed scaffolds, stress-test belief systems, and run AEE pipelines."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -184,6 +184,7 @@ class AgentRunner:
184
184
  max_tool_iterations: int = 10,
185
185
  optimize: bool = False,
186
186
  optimization_config: OptimizationConfig | None = None,
187
+ json_events: bool = False,
187
188
  ) -> None:
188
189
  self.project_dir = str(Path(project_dir).resolve())
189
190
  self._provider_name = provider_name
@@ -191,6 +192,7 @@ class AgentRunner:
191
192
  self._tier = tier
192
193
  self._stream = stream
193
194
  self._max_iterations = max_tool_iterations
195
+ self._json_events = json_events
194
196
 
195
197
  self._provider: Any = None
196
198
  self._state = SessionState(project_dir=self.project_dir)
@@ -291,7 +293,10 @@ class AgentRunner:
291
293
  except Exception as e: # noqa: BLE001
292
294
  error_msg = f"[Provider error] {e}"
293
295
  if not silent:
294
- self._print(error_msg)
296
+ if self._json_events:
297
+ self._emit_event(type="error", message=error_msg)
298
+ else:
299
+ self._print(error_msg)
295
300
  return error_msg
296
301
 
297
302
  # Update credit tracking
@@ -299,6 +304,15 @@ class AgentRunner:
299
304
  self._state.total_output_tokens += response.output_tokens
300
305
  self._state.total_cost_usd += response.estimated_cost_usd
301
306
 
307
+ # Emit token update event
308
+ if self._json_events and not silent:
309
+ self._emit_event(
310
+ type="tokens",
311
+ in_tokens=self._state.total_input_tokens,
312
+ out_tokens=self._state.total_output_tokens,
313
+ cost_usd=self._state.total_cost_usd,
314
+ )
315
+
302
316
  if response.content:
303
317
  final_response = response.content
304
318
 
@@ -330,6 +344,14 @@ class AgentRunner:
330
344
  )
331
345
  )
332
346
 
347
+ # Emit turn-done event
348
+ if self._json_events and not silent:
349
+ self._emit_event(
350
+ type="turn_done",
351
+ total_tokens=self._state.session_tokens,
352
+ cost_usd=self._state.total_cost_usd,
353
+ )
354
+
333
355
  return final_response
334
356
 
335
357
  def _call_provider(self, messages: list[Message], silent: bool = False) -> CompletionResponse:
@@ -362,7 +384,7 @@ class AgentRunner:
362
384
  messages = hint.messages
363
385
  tools = hint.tools
364
386
 
365
- use_stream = self._stream and not silent and not tools
387
+ use_stream = self._stream and not silent and not tools and not self._json_events
366
388
  if use_stream:
367
389
  accumulated = ""
368
390
  for token in provider.stream(messages, tools=None):
@@ -375,7 +397,10 @@ class AgentRunner:
375
397
  else:
376
398
  response = cast(CompletionResponse, provider.complete(messages, tools=tools))
377
399
  if not silent and response.content:
378
- self._print(response.content)
400
+ if self._json_events:
401
+ self._emit_event(type="llm_chunk", text=response.content)
402
+ else:
403
+ self._print(response.content)
379
404
 
380
405
  # ── Optimization post-call ───────────────────────────────────────────
381
406
  if self._optimizer is not None and hint is not None:
@@ -405,7 +430,10 @@ class AgentRunner:
405
430
  inputs = tc.get("input", {})
406
431
 
407
432
  if not silent:
408
- self._print(f"\n[Tool: {name}]")
433
+ if self._json_events:
434
+ self._emit_event(type="tool_started", name=name, args=inputs)
435
+ else:
436
+ self._print(f"\n[Tool: {name}]")
409
437
 
410
438
  # Fire pre_tool hooks
411
439
  pre_ctx = HookContext(
@@ -451,9 +479,12 @@ class AgentRunner:
451
479
  elapsed = time.time() * 1000 - start_ms
452
480
 
453
481
  if not silent:
454
- # Truncate long outputs for display
455
- display = output[:500] + "..." if len(output) > 500 else output
456
- self._print(f" → {display}")
482
+ if self._json_events:
483
+ self._emit_event(type="tool_finished", name=name, result=output, is_error=error)
484
+ else:
485
+ # Truncate long outputs for display
486
+ display = output[:500] + "..." if len(output) > 500 else output
487
+ self._print(f" → {display}")
457
488
 
458
489
  tr = ToolResult(
459
490
  tool_name=name,
@@ -554,13 +585,23 @@ class AgentRunner:
554
585
  def _print_banner(self) -> None:
555
586
  provider = getattr(self._provider, "provider_name", "?")
556
587
  model = getattr(self._provider, "model", "?")
557
- self._print(
558
- f"\n[specsmith agent — AEE-integrated]"
559
- f"\n Project: {self.project_dir}"
560
- f"\n Provider: {provider}/{model}"
561
- f"\n Tools: {len(self._tools)} | Skills: {len(self._skills)}"
562
- f"\n Type /help for commands, exit to quit\n"
563
- )
588
+ if self._json_events:
589
+ self._emit_event(
590
+ type="ready",
591
+ provider=provider,
592
+ model=model,
593
+ project_dir=self.project_dir,
594
+ tools=len(self._tools),
595
+ skills=len(self._skills),
596
+ )
597
+ else:
598
+ self._print(
599
+ f"\n[specsmith agent — AEE-integrated]"
600
+ f"\n Project: {self.project_dir}"
601
+ f"\n Provider: {provider}/{model}"
602
+ f"\n Tools: {len(self._tools)} | Skills: {len(self._skills)}"
603
+ f"\n Type /help for commands, exit to quit\n"
604
+ )
564
605
 
565
606
  def _print_status(self) -> None:
566
607
  self._print(
@@ -594,10 +635,22 @@ class AgentRunner:
594
635
  def _prompt(self) -> str:
595
636
  """Read a line of input from stdin."""
596
637
  try:
597
- return input("\n> ")
638
+ # In json_events mode suppress the prompt string so stdout stays pure JSON
639
+ return input("" if self._json_events else "\n> ")
598
640
  except EOFError:
599
641
  raise
600
642
 
601
643
  def _print(self, text: str = "", end: str = "\n", flush: bool = False) -> None:
602
- """Print to stdout."""
603
- print(text, end=end, flush=flush)
644
+ """Print to stdout; in json_events mode emit a system event instead."""
645
+ if self._json_events:
646
+ if text.strip():
647
+ self._emit_event(type="system", message=text.strip())
648
+ else:
649
+ print(text, end=end, flush=flush)
650
+
651
+ def _emit_event(self, **kwargs: Any) -> None:
652
+ """Emit a newline-delimited JSON event to stdout (json_events mode only)."""
653
+ import json
654
+ import sys
655
+
656
+ print(json.dumps(kwargs), flush=True, file=sys.stdout) # noqa: T201
@@ -1809,29 +1809,6 @@ def plugin_list() -> None:
1809
1809
  console.print(f"\n {len(plugins)} plugin(s)")
1810
1810
 
1811
1811
 
1812
- # ---------------------------------------------------------------------------
1813
- # Serve (API for React dashboard)
1814
- # ---------------------------------------------------------------------------
1815
-
1816
-
1817
- @main.command()
1818
- @click.option("--port", default=8910, help="Port to serve on.")
1819
- def serve(port: int) -> None:
1820
- """Start local API server for the web dashboard."""
1821
- console.print(f"[bold]Starting specsmith API server on port {port}...[/bold]")
1822
- console.print("[yellow]Not yet implemented. See issue #14.[/yellow]")
1823
- console.print(
1824
- "\nPlanned endpoints:\n"
1825
- " GET /api/projects \u2014 list governed projects\n"
1826
- " POST /api/projects/init \u2014 scaffold new project\n"
1827
- " POST /api/projects/import \u2014 import existing project\n"
1828
- " GET /api/projects/:id/audit \u2014 run audit\n"
1829
- " GET /api/projects/:id/export \u2014 generate report\n"
1830
- " GET /api/types \u2014 list all 30 project types\n"
1831
- " GET /api/tools/:type \u2014 tool registry for a type"
1832
- )
1833
-
1834
-
1835
1812
  # ---------------------------------------------------------------------------
1836
1813
  # Process execution and abort
1837
1814
  # ---------------------------------------------------------------------------
@@ -1955,6 +1932,13 @@ def abort_cmd(pid: int | None, abort_all_flag: bool, project_dir: str) -> None:
1955
1932
  default=False,
1956
1933
  help="Enable token optimization (caching, routing, context trim, tool filtering).",
1957
1934
  )
1935
+ @click.option(
1936
+ "--json-events",
1937
+ "json_events",
1938
+ is_flag=True,
1939
+ default=False,
1940
+ help="Emit structured JSONL events to stdout (used by IDE clients like the VS Code extension).",
1941
+ )
1958
1942
  def run_cmd(
1959
1943
  project_dir: str,
1960
1944
  task: str,
@@ -1963,6 +1947,7 @@ def run_cmd(
1963
1947
  tier: str,
1964
1948
  no_stream: bool,
1965
1949
  optimize: bool,
1950
+ json_events: bool,
1966
1951
  ) -> None:
1967
1952
  """Start the AEE-integrated agentic client REPL.
1968
1953
 
@@ -1994,6 +1979,7 @@ def run_cmd(
1994
1979
  tier=tier_map[tier],
1995
1980
  stream=not no_stream,
1996
1981
  optimize=optimize,
1982
+ json_events=json_events,
1997
1983
  )
1998
1984
  if task:
1999
1985
  result = runner.run_task(task)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specsmith
3
- Version: 0.3.0.dev138
3
+ Version: 0.3.0.dev139
4
4
  Summary: Applied Epistemic Engineering toolkit — forge epistemically-governed scaffolds, stress-test belief systems, and run AEE pipelines.
5
5
  Author: BitConcepts
6
6
  License-Expression: MIT