@1mancompany/onemancompany 0.7.48 → 0.7.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
>
|
|
32
32
|
> Not building a company — building any company.
|
|
33
33
|
|
|
34
|
-
OneManCompany is an open-source OS that lets anyone build and run a complete AI-powered company from their browser.
|
|
34
|
+
OneManCompany is an open-source OS that lets anyone build and run a complete AI-powered company from their browser. It doesn't replace tools like Claude Code, Codex, or other agent frameworks — it operates one level above them as an **agentic operating system**, orchestrating hierarchical AI teams built on top of these underlying tools.
|
|
35
35
|
|
|
36
36
|
**You are the CEO — the only human.** Everyone else — HR, COO, engineers, designers — are AI employees that think, collaborate, and deliver real work autonomously. (*No slacking, no sick days, no raise requests — just the occasional need for a pep talk.*)
|
|
37
37
|
|
|
@@ -198,7 +198,7 @@ These aren't toy demos — each AI company produces **product-level deliverables
|
|
|
198
198
|
|
|
199
199
|
## Quick Start
|
|
200
200
|
|
|
201
|
-
You only need **Node.js
|
|
201
|
+
You only need **Node.js 18+** and **Git**. Everything else is installed automatically.
|
|
202
202
|
|
|
203
203
|
```bash
|
|
204
204
|
npx @1mancompany/onemancompany
|
|
@@ -261,7 +261,7 @@ Founding employees (EA, HR, COO, CSO) support three execution modes, switchable
|
|
|
261
261
|
| --- | --- | --- |
|
|
262
262
|
| **Company Hosted Agent** | OMC's built-in agent, calls LLMs via OpenRouter | OpenRouter API Key (configured in setup process) |
|
|
263
263
|
| **Claude Code** | More capable, lower token cost | Install [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) + [Claude Pro/Max subscription](https://claude.ai) |
|
|
264
|
-
| **OpenClaw** *(
|
|
264
|
+
| **OpenClaw** *(Experimental)* | Open-source alternative, multiple LLM backends | Install [OpenClaw CLI](https://github.com/openclaw/openclaw) + compatible LLM API Key |
|
|
265
265
|
|
|
266
266
|
Defaults to Company Hosted Agent — no extra subscription needed to get started. See [Execution Modes docs](https://1mancompany.github.io/OneManCompany/docs/guide/execution-modes/) for details.
|
|
267
267
|
|
|
@@ -418,7 +418,7 @@ This is a living plan — [request a feature](https://github.com/1mancompany/One
|
|
|
418
418
|
| [Vessel System](docs/vessel-system.md) | Vessel + Talent deep dive, Harness protocols |
|
|
419
419
|
| [Task System](docs/task-system.md) | Task status state machine |
|
|
420
420
|
| [Coding Guide](vibe-coding-guide.md) | Coding guidelines, testing rules, code style |
|
|
421
|
-
| [Changelog](
|
|
421
|
+
| [Changelog](https://github.com/1mancompany/OneManCompany/releases) | Release history |
|
|
422
422
|
|
|
423
423
|
---
|
|
424
424
|
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -91,6 +91,10 @@ class TaskNode:
|
|
|
91
91
|
# Used to cap infinite retry loops (e.g. EA keeps retrying a failing child).
|
|
92
92
|
retry_count: int = 0
|
|
93
93
|
|
|
94
|
+
# How many times this node was retried due to stall detection
|
|
95
|
+
# (agent promised action but didn't call tools). Capped at MAX_STALL_RETRIES.
|
|
96
|
+
stall_retry_count: int = 0
|
|
97
|
+
|
|
94
98
|
# --- Content externalization tracking (not part of equality/repr) ---
|
|
95
99
|
_content_dirty: bool = field(default=False, init=False, repr=False, compare=False)
|
|
96
100
|
_content_loaded: bool = field(default=False, init=False, repr=False, compare=False)
|
|
@@ -210,6 +214,7 @@ class TaskNode:
|
|
|
210
214
|
"hold_reason": self.hold_reason,
|
|
211
215
|
"hold_started_at": self.hold_started_at,
|
|
212
216
|
"retry_count": self.retry_count,
|
|
217
|
+
"stall_retry_count": self.stall_retry_count,
|
|
213
218
|
"directives_count": len(self.directives),
|
|
214
219
|
}
|
|
215
220
|
|
|
@@ -139,11 +139,14 @@ _PROMISE_PATTERNS = _re.compile(
|
|
|
139
139
|
r"我将|接下来|下一步|现在开始|马上开始|即将开始|准备开始"
|
|
140
140
|
r"|我会(?:立即|马上|开始)"
|
|
141
141
|
r"|下面我(?:来|将|要)"
|
|
142
|
+
r"|分配给\w+处理|派遣给\w+负责"
|
|
142
143
|
# English future-action phrases
|
|
143
144
|
r"|I will (?:now |start |begin )|I'll (?:now |start |begin )"
|
|
144
145
|
r"|Let me (?:start|begin|proceed)"
|
|
145
146
|
r"|Next,? I'?(?:ll| will)"
|
|
146
147
|
r"|I'?m going to (?:start|begin)"
|
|
148
|
+
r"|Going to dispatch"
|
|
149
|
+
r"|I need to dispatch_child"
|
|
147
150
|
r")",
|
|
148
151
|
_re.IGNORECASE,
|
|
149
152
|
)
|
|
@@ -160,6 +163,27 @@ def detect_unfulfilled_promises(output: str | None) -> bool:
|
|
|
160
163
|
return bool(_PROMISE_PATTERNS.search(output))
|
|
161
164
|
|
|
162
165
|
|
|
166
|
+
MAX_STALL_RETRIES: int = 2 # max times to re-run a stalled agent before giving up
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _should_retry_stall(node) -> bool:
|
|
170
|
+
"""Check if a completed node should be retried due to stall detection.
|
|
171
|
+
|
|
172
|
+
Returns True if:
|
|
173
|
+
- Node is not a system node
|
|
174
|
+
- Node has no children (didn't actually dispatch)
|
|
175
|
+
- Node output contains promise patterns
|
|
176
|
+
- stall_retry_count < MAX_STALL_RETRIES
|
|
177
|
+
"""
|
|
178
|
+
if node.node_type in SYSTEM_NODE_TYPES:
|
|
179
|
+
return False
|
|
180
|
+
if node.children_ids:
|
|
181
|
+
return False
|
|
182
|
+
if not detect_unfulfilled_promises(node.result):
|
|
183
|
+
return False
|
|
184
|
+
return getattr(node, 'stall_retry_count', 0) < MAX_STALL_RETRIES
|
|
185
|
+
|
|
186
|
+
|
|
163
187
|
# ---------------------------------------------------------------------------
|
|
164
188
|
# Dependency context builder
|
|
165
189
|
# ---------------------------------------------------------------------------
|
|
@@ -1732,18 +1756,42 @@ class EmployeeManager:
|
|
|
1732
1756
|
employee_id, entry.node_id)
|
|
1733
1757
|
|
|
1734
1758
|
# Stall detection: agent said "I will do X" but dispatched no children
|
|
1735
|
-
if (node
|
|
1759
|
+
if _should_retry_stall(node):
|
|
1760
|
+
node.stall_retry_count = getattr(node, 'stall_retry_count', 0) + 1
|
|
1761
|
+
logger.warning(
|
|
1762
|
+
"[STALL] employee={} node={}: output contains action promises "
|
|
1763
|
+
"but no subtasks dispatched. Retrying ({}/{}).",
|
|
1764
|
+
employee_id, entry.node_id,
|
|
1765
|
+
node.stall_retry_count, MAX_STALL_RETRIES,
|
|
1766
|
+
)
|
|
1767
|
+
# Revert to PROCESSING and re-schedule with explicit nudge
|
|
1768
|
+
node.set_status(TaskPhase.PROCESSING)
|
|
1769
|
+
nudge = (
|
|
1770
|
+
"\n\n[SYSTEM] You said you would dispatch tasks but did NOT "
|
|
1771
|
+
"actually call dispatch_child(). You MUST call the tool now. "
|
|
1772
|
+
"Do NOT describe what you plan to do — invoke dispatch_child() directly."
|
|
1773
|
+
)
|
|
1774
|
+
node.result = (node.result or "") + nudge
|
|
1775
|
+
save_tree_async(entry.tree_path)
|
|
1776
|
+
self.schedule_node(employee_id, entry.node_id, entry.tree_path)
|
|
1777
|
+
self._schedule_next(employee_id)
|
|
1778
|
+
self._log_node(employee_id, entry.node_id, "stall_retry",
|
|
1779
|
+
f"Retrying stalled task (attempt {node.stall_retry_count})")
|
|
1780
|
+
return # skip normal completion flow
|
|
1781
|
+
elif (node.node_type not in SYSTEM_NODE_TYPES
|
|
1736
1782
|
and not node.children_ids
|
|
1737
1783
|
and detect_unfulfilled_promises(node.result)):
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
"
|
|
1784
|
+
# Max retries exhausted — warn CEO
|
|
1785
|
+
logger.warning(
|
|
1786
|
+
"[STALL] employee={} node={}: stall retries exhausted ({}/{}). "
|
|
1787
|
+
"Marking COMPLETED with warning.",
|
|
1741
1788
|
employee_id, entry.node_id,
|
|
1789
|
+
getattr(node, 'stall_retry_count', 0), MAX_STALL_RETRIES,
|
|
1742
1790
|
)
|
|
1743
|
-
self._push_to_conversation(
|
|
1791
|
+
self._push_to_conversation(
|
|
1744
1792
|
node,
|
|
1745
|
-
"⚠️ Agent claimed it would execute follow-up work but
|
|
1746
|
-
"create any tasks
|
|
1793
|
+
"⚠️ Agent repeatedly claimed it would execute follow-up work but "
|
|
1794
|
+
"did not create any tasks after multiple retries. Please review and re-dispatch manually.",
|
|
1747
1795
|
)
|
|
1748
1796
|
|
|
1749
1797
|
save_tree_async(entry.tree_path)
|
|
@@ -1799,6 +1847,11 @@ class EmployeeManager:
|
|
|
1799
1847
|
|
|
1800
1848
|
# Unschedule completed node
|
|
1801
1849
|
self.unschedule(employee_id, entry.node_id)
|
|
1850
|
+
|
|
1851
|
+
# Drain any deferred schedules — ensures child tasks dispatched
|
|
1852
|
+
# by tools (e.g. dispatch_child) that hit a sync/async boundary
|
|
1853
|
+
# actually start executing (I1: prevents silent defer).
|
|
1854
|
+
self.drain_pending()
|
|
1802
1855
|
else:
|
|
1803
1856
|
self._publish_node_update(employee_id, node)
|
|
1804
1857
|
|