bareagent-cli 0.1.0__py3-none-any.whl

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 (121) hide show
  1. bareagent/__init__.py +10 -0
  2. bareagent/concurrency/__init__.py +6 -0
  3. bareagent/concurrency/background.py +97 -0
  4. bareagent/concurrency/notification.py +61 -0
  5. bareagent/concurrency/scheduler.py +136 -0
  6. bareagent/config.toml +299 -0
  7. bareagent/core/__init__.py +1 -0
  8. bareagent/core/config_paths.py +49 -0
  9. bareagent/core/context.py +127 -0
  10. bareagent/core/fileutil.py +103 -0
  11. bareagent/core/goal.py +214 -0
  12. bareagent/core/handlers/__init__.py +1 -0
  13. bareagent/core/handlers/bash.py +79 -0
  14. bareagent/core/handlers/file_edit.py +47 -0
  15. bareagent/core/handlers/file_read.py +270 -0
  16. bareagent/core/handlers/file_write.py +34 -0
  17. bareagent/core/handlers/glob_search.py +30 -0
  18. bareagent/core/handlers/goal.py +60 -0
  19. bareagent/core/handlers/grep_search.py +52 -0
  20. bareagent/core/handlers/memory.py +71 -0
  21. bareagent/core/handlers/plan.py +106 -0
  22. bareagent/core/handlers/search_utils.py +77 -0
  23. bareagent/core/handlers/skill.py +87 -0
  24. bareagent/core/handlers/subagent_send.py +70 -0
  25. bareagent/core/handlers/web_fetch.py +126 -0
  26. bareagent/core/handlers/web_search.py +165 -0
  27. bareagent/core/handlers/workflow.py +190 -0
  28. bareagent/core/loop.py +535 -0
  29. bareagent/core/retry.py +131 -0
  30. bareagent/core/sandbox.py +27 -0
  31. bareagent/core/schema.py +21 -0
  32. bareagent/core/tools.py +779 -0
  33. bareagent/core/workflow.py +517 -0
  34. bareagent/core/workflow_registry.py +219 -0
  35. bareagent/debug/__init__.py +0 -0
  36. bareagent/debug/interaction_log.py +263 -0
  37. bareagent/debug/viewer.html +1750 -0
  38. bareagent/debug/web_viewer.py +157 -0
  39. bareagent/hooks/__init__.py +32 -0
  40. bareagent/hooks/config.py +118 -0
  41. bareagent/hooks/engine.py +197 -0
  42. bareagent/hooks/errors.py +14 -0
  43. bareagent/hooks/events.py +22 -0
  44. bareagent/lsp/__init__.py +63 -0
  45. bareagent/lsp/config.py +134 -0
  46. bareagent/lsp/coord.py +118 -0
  47. bareagent/lsp/diagnostics.py +240 -0
  48. bareagent/lsp/errors.py +24 -0
  49. bareagent/lsp/manager.py +866 -0
  50. bareagent/lsp/tools.py +629 -0
  51. bareagent/lsp/workspace_edit.py +305 -0
  52. bareagent/main.py +4205 -0
  53. bareagent/mcp/__init__.py +69 -0
  54. bareagent/mcp/_sse.py +69 -0
  55. bareagent/mcp/client.py +341 -0
  56. bareagent/mcp/config.py +169 -0
  57. bareagent/mcp/errors.py +32 -0
  58. bareagent/mcp/manager.py +318 -0
  59. bareagent/mcp/protocol.py +187 -0
  60. bareagent/mcp/registry.py +557 -0
  61. bareagent/mcp/transport/__init__.py +15 -0
  62. bareagent/mcp/transport/base.py +149 -0
  63. bareagent/mcp/transport/http_legacy.py +192 -0
  64. bareagent/mcp/transport/http_streamable.py +217 -0
  65. bareagent/mcp/transport/stdio.py +202 -0
  66. bareagent/memory/__init__.py +1 -0
  67. bareagent/memory/compact.py +203 -0
  68. bareagent/memory/conversation_io.py +226 -0
  69. bareagent/memory/embedding.py +194 -0
  70. bareagent/memory/persistent.py +515 -0
  71. bareagent/memory/token_counter.py +67 -0
  72. bareagent/memory/token_tracker.py +262 -0
  73. bareagent/memory/transcript.py +100 -0
  74. bareagent/permission/__init__.py +1 -0
  75. bareagent/permission/guard.py +329 -0
  76. bareagent/permission/rules.py +19 -0
  77. bareagent/planning/__init__.py +19 -0
  78. bareagent/planning/agent_types.py +169 -0
  79. bareagent/planning/skill_gen.py +141 -0
  80. bareagent/planning/skill_store.py +173 -0
  81. bareagent/planning/skills.py +146 -0
  82. bareagent/planning/subagent.py +355 -0
  83. bareagent/planning/subagent_registry.py +77 -0
  84. bareagent/planning/tasks.py +348 -0
  85. bareagent/planning/todo.py +153 -0
  86. bareagent/planning/worktree.py +122 -0
  87. bareagent/provider/__init__.py +1 -0
  88. bareagent/provider/anthropic.py +348 -0
  89. bareagent/provider/base.py +136 -0
  90. bareagent/provider/factory.py +130 -0
  91. bareagent/provider/openai.py +881 -0
  92. bareagent/provider/presets.py +72 -0
  93. bareagent/provider/setup.py +356 -0
  94. bareagent/skills/.gitkeep +1 -0
  95. bareagent/skills/code-review/SKILL.md +68 -0
  96. bareagent/skills/git/SKILL.md +68 -0
  97. bareagent/skills/test/SKILL.md +70 -0
  98. bareagent/team/__init__.py +17 -0
  99. bareagent/team/autonomous.py +193 -0
  100. bareagent/team/mailbox.py +239 -0
  101. bareagent/team/manager.py +155 -0
  102. bareagent/team/protocols.py +129 -0
  103. bareagent/tracing/__init__.py +12 -0
  104. bareagent/tracing/_api.py +92 -0
  105. bareagent/tracing/_proxy.py +60 -0
  106. bareagent/tracing/composite.py +115 -0
  107. bareagent/tracing/json_file.py +115 -0
  108. bareagent/tracing/langfuse.py +139 -0
  109. bareagent/tracing/otel.py +107 -0
  110. bareagent/tracing/setup.py +85 -0
  111. bareagent/ui/__init__.py +24 -0
  112. bareagent/ui/console.py +167 -0
  113. bareagent/ui/prompt.py +78 -0
  114. bareagent/ui/protocol.py +24 -0
  115. bareagent/ui/stream.py +66 -0
  116. bareagent/ui/theme.py +240 -0
  117. bareagent_cli-0.1.0.dist-info/METADATA +331 -0
  118. bareagent_cli-0.1.0.dist-info/RECORD +121 -0
  119. bareagent_cli-0.1.0.dist-info/WHEEL +4 -0
  120. bareagent_cli-0.1.0.dist-info/entry_points.txt +2 -0
  121. bareagent_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,190 @@
1
+ """Handler + schema for the ``workflow`` tool (deterministic DAG orchestration).
2
+
3
+ Like ``exit_plan_mode`` / ``goal_verdict`` / ``skill_create``, ``workflow`` is a
4
+ main-loop-only tool: its schema is NOT in the global ``get_tools()`` set, it is
5
+ appended only to the top-level ``loop_tools`` and its handler is installed on the
6
+ main loop's handler dict (see ``main.py``). ``"workflow"`` is also in
7
+ ``agent_types.MAIN_LOOP_ONLY_TOOLS`` so ``filter_tools`` strips it from every
8
+ sub-agent type, and ``filter_handlers`` then drops the orphaned handler -- a
9
+ sub-agent can never fan out its own workflow (no nesting in the MVP).
10
+
11
+ The LLM authors the DAG on the fly: a ``nodes`` array of declarative subagent
12
+ tasks with ``depends_on`` edges (not executable code). The handler is a thin
13
+ shim: parse -> validate -> drive the pure :func:`bareagent.core.workflow.run_workflow`
14
+ engine with the caller-injected ``execute_node`` / ``map_concurrent`` /
15
+ ``on_progress`` callbacks -> format the aggregated summary. Returning an
16
+ ``Error:`` string for bad input (rather than raising) keeps the main loop's tool
17
+ result clean (see ``error-handling.md``).
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ from collections.abc import Callable
23
+ from typing import Any
24
+
25
+ from bareagent.core.schema import tool_schema
26
+ from bareagent.core.workflow import (
27
+ DEFAULT_MAX_NODES,
28
+ NodeResult,
29
+ WorkflowError,
30
+ WorkflowNode,
31
+ WorkflowSpec,
32
+ compute_resume_plan,
33
+ format_summary,
34
+ parse_workflow,
35
+ run_workflow,
36
+ validate_workflow,
37
+ )
38
+
39
+ WORKFLOW_TOOL_SCHEMA = tool_schema(
40
+ "workflow",
41
+ (
42
+ "Run a deterministic DAG of subagent tasks in parallel. Provide 'nodes': "
43
+ "each node is an isolated subagent given a 'prompt'; independent nodes run "
44
+ "concurrently and nodes wait for their 'depends_on' nodes. Reference an "
45
+ "upstream node's output in a prompt with {{node_id}}. Use this when you can "
46
+ "decompose the work into independent or dependency-ordered pieces up front; "
47
+ "it returns a structured summary of every node's result. The structure is "
48
+ "fixed once submitted (no loops/conditionals); issue another workflow call "
49
+ "to branch on the results. Set 'run_in_background' to get a run id back "
50
+ "immediately and have the result delivered when it finishes (watch it with "
51
+ "/workflows). Set 'resume_from' to a prior run id to reuse that run's "
52
+ "unchanged completed nodes and only re-run changed/failed/new ones. Set "
53
+ "'token_budget' to cap the run: once spent, remaining nodes are skipped."
54
+ ),
55
+ {
56
+ "run_in_background": {
57
+ "type": "boolean",
58
+ "description": (
59
+ "Run asynchronously: return a run id now and deliver the full "
60
+ "summary when it finishes (default false = block and return it)."
61
+ ),
62
+ },
63
+ "resume_from": {
64
+ "type": "string",
65
+ "description": (
66
+ "A prior workflow run id. Nodes with the same id and an unchanged "
67
+ "prompt that completed last run are reused (not re-executed); "
68
+ "changed/failed/new nodes and everything downstream of them re-run. "
69
+ "An unknown id is ignored (the whole DAG runs fresh)."
70
+ ),
71
+ },
72
+ "token_budget": {
73
+ "type": "integer",
74
+ "description": (
75
+ "Soft token ceiling for this run. Checked before each layer; once "
76
+ "spent tokens reach it, remaining nodes are skipped. Omit/0 = no cap."
77
+ ),
78
+ },
79
+ "nodes": {
80
+ "type": "array",
81
+ "description": "The DAG nodes. Ids must be unique and the graph acyclic.",
82
+ "items": {
83
+ "type": "object",
84
+ "properties": {
85
+ "id": {
86
+ "type": "string",
87
+ "description": "Unique node id (referenced by depends_on and {{id}}).",
88
+ },
89
+ "prompt": {
90
+ "type": "string",
91
+ "description": "The task for this node's subagent.",
92
+ },
93
+ "agent_type": {
94
+ "type": "string",
95
+ "description": (
96
+ "Optional subagent profile (e.g. general-purpose, explore, "
97
+ "plan, code-review). Defaults to the configured default."
98
+ ),
99
+ },
100
+ "depends_on": {
101
+ "type": "array",
102
+ "items": {"type": "string"},
103
+ "description": "Ids of nodes whose outputs must complete first.",
104
+ },
105
+ "phase": {
106
+ "type": "string",
107
+ "description": "Optional label grouping nodes in the summary.",
108
+ },
109
+ "label": {
110
+ "type": "string",
111
+ "description": "Optional short human-readable node label.",
112
+ },
113
+ },
114
+ "required": ["id", "prompt"],
115
+ },
116
+ }
117
+ },
118
+ ["nodes"],
119
+ )
120
+
121
+
122
+ def validate_workflow_input(
123
+ nodes: Any, *, max_nodes: int = DEFAULT_MAX_NODES
124
+ ) -> WorkflowSpec | str:
125
+ """Parse + validate raw ``nodes`` into a spec, or return an ``Error:`` string.
126
+
127
+ Split out so ``main.py`` can validate once up front (immediate feedback for a
128
+ malformed DAG, even when ``run_in_background`` is set) and then reuse the
129
+ parsed spec without re-parsing.
130
+ """
131
+ try:
132
+ spec = parse_workflow({"nodes": nodes})
133
+ except WorkflowError as exc:
134
+ return f"Error: {exc}"
135
+ errors = validate_workflow(spec, max_nodes=max_nodes)
136
+ if errors:
137
+ return "Error: invalid workflow:\n" + "\n".join(f"- {error}" for error in errors)
138
+ return spec
139
+
140
+
141
+ def run_workflow_tool(
142
+ *,
143
+ nodes: Any = None,
144
+ spec: WorkflowSpec | None = None,
145
+ resume_from: str | None = None,
146
+ token_budget: int = 0,
147
+ execute_node: Callable[[WorkflowNode, dict[str, NodeResult]], Any],
148
+ map_concurrent: Callable[[list[Callable[[], NodeResult]]], list[NodeResult]],
149
+ on_progress: Callable[[str], None] | None = None,
150
+ on_node_status: Callable[[str, NodeResult], None] | None = None,
151
+ resolve_prior: Callable[[str], tuple[WorkflowSpec, dict[str, NodeResult]] | None] | None = None,
152
+ tokens_spent: Callable[[], int] | None = None,
153
+ max_nodes: int = DEFAULT_MAX_NODES,
154
+ ) -> str:
155
+ """Resolve resume, run, and summarize an LLM-authored workflow DAG.
156
+
157
+ Pass a pre-validated ``spec`` to skip parsing (``main.py`` does this so it can
158
+ register the run before driving); otherwise raw ``nodes`` are parsed +
159
+ validated here, returning an ``Error:`` string for an unusable DAG.
160
+
161
+ Resume: when ``resume_from`` and ``resolve_prior`` are given and the prior run
162
+ is found, :func:`compute_resume_plan` decides which nodes to reuse. An unknown
163
+ id falls open to a fresh run. Budget: ``token_budget`` (>0) plus ``tokens_spent``
164
+ stop the run at a layer boundary once spent. ``on_node_status`` mirrors each
165
+ node's terminal state out to the registry for the ``/workflows`` panel.
166
+ """
167
+ if spec is None:
168
+ validated = validate_workflow_input(nodes, max_nodes=max_nodes)
169
+ if isinstance(validated, str):
170
+ return validated
171
+ spec = validated
172
+
173
+ reused: dict[str, NodeResult] = {}
174
+ if resume_from and resolve_prior is not None:
175
+ prior = resolve_prior(resume_from)
176
+ if prior is not None:
177
+ prior_spec, prior_results = prior
178
+ reused = compute_resume_plan(spec, prior_spec, prior_results)
179
+
180
+ results = run_workflow(
181
+ spec,
182
+ execute_node=execute_node,
183
+ map_concurrent=map_concurrent,
184
+ on_progress=on_progress,
185
+ on_node_status=on_node_status,
186
+ reused_results=reused,
187
+ token_budget=token_budget if token_budget and token_budget > 0 else 0,
188
+ tokens_spent=tokens_spent,
189
+ )
190
+ return format_summary(spec, results)