@poncho-ai/harness 0.37.2 → 0.39.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.
- package/.turbo/turbo-build.log +5 -5
- package/CHANGELOG.md +216 -0
- package/dist/index.d.ts +397 -34
- package/dist/index.js +2228 -130
- package/package.json +2 -2
- package/src/harness.ts +48 -72
- package/src/index.ts +1 -0
- package/src/local-tools.ts +4 -3
- package/src/mcp.ts +9 -6
- package/src/orchestrator/continuation.ts +13 -0
- package/src/orchestrator/history.ts +69 -0
- package/src/orchestrator/index.ts +54 -0
- package/src/orchestrator/orchestrator.ts +1535 -0
- package/src/orchestrator/subagents.ts +27 -0
- package/src/orchestrator/turn.ts +367 -0
- package/src/reminder-store.ts +183 -16
- package/src/reminder-tools.ts +102 -6
- package/src/state.ts +127 -3
- package/src/storage/engine.ts +29 -10
- package/src/storage/memory-engine.ts +74 -10
- package/src/storage/postgres-engine.ts +1 -0
- package/src/storage/schema.ts +21 -0
- package/src/storage/sql-dialect.ts +294 -23
- package/src/storage/sqlite-engine.ts +1 -0
- package/src/storage/store-adapters.ts +17 -11
- package/src/telemetry.ts +10 -7
- package/src/upload-store.ts +7 -4
- package/src/vfs/bash-manager.ts +16 -2
- package/src/vfs/edit-file-tool.ts +9 -8
- package/src/vfs/read-file-tool.ts +14 -15
- package/src/vfs/write-file-tool.ts +6 -5
- package/test/orchestrator.test.ts +176 -0
- package/test/reminder-store.test.ts +193 -4
- package/test/state.test.ts +21 -0
- package/test/storage-engine.test.ts +80 -0
|
@@ -64,6 +64,86 @@ function runEngineTests(name: string, factory: () => Promise<{ engine: StorageEn
|
|
|
64
64
|
expect(results).toHaveLength(1);
|
|
65
65
|
expect(results[0].title).toBe("alpha beta");
|
|
66
66
|
});
|
|
67
|
+
|
|
68
|
+
it("persists parentConversationId atomically when provided to create", async () => {
|
|
69
|
+
const parent = await engine.conversations.create("o", "Parent");
|
|
70
|
+
const child = await engine.conversations.create("o", "Child", null, {
|
|
71
|
+
parentConversationId: parent.conversationId,
|
|
72
|
+
subagentMeta: { task: "do thing", status: "running" },
|
|
73
|
+
messages: [{ role: "user", content: "do thing" }],
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Returned object reflects init fields
|
|
77
|
+
expect(child.parentConversationId).toBe(parent.conversationId);
|
|
78
|
+
expect(child.subagentMeta?.task).toBe("do thing");
|
|
79
|
+
expect(child.messages).toHaveLength(1);
|
|
80
|
+
|
|
81
|
+
// listSummaries reads the dedicated column — child must be linked to parent.
|
|
82
|
+
const summaries = await engine.conversations.list("o");
|
|
83
|
+
const childSummary = summaries.find((s) => s.conversationId === child.conversationId);
|
|
84
|
+
expect(childSummary?.parentConversationId).toBe(parent.conversationId);
|
|
85
|
+
|
|
86
|
+
// get() rehydrates from data blob — parent + meta must round-trip.
|
|
87
|
+
const reloaded = await engine.conversations.get(child.conversationId);
|
|
88
|
+
expect(reloaded?.parentConversationId).toBe(parent.conversationId);
|
|
89
|
+
expect(reloaded?.subagentMeta?.task).toBe("do thing");
|
|
90
|
+
expect(reloaded?.messages).toHaveLength(1);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("persists thread anchor (parentMessageId + threadMeta) and lists threads", async () => {
|
|
94
|
+
const parent = await engine.conversations.create("o", "Parent");
|
|
95
|
+
const anchorId = "msg-anchor-1";
|
|
96
|
+
const thread = await engine.conversations.create("o", "Thread A", null, {
|
|
97
|
+
parentConversationId: parent.conversationId,
|
|
98
|
+
parentMessageId: anchorId,
|
|
99
|
+
messages: [
|
|
100
|
+
{ role: "user", content: "hi", metadata: { id: "m0" } },
|
|
101
|
+
{ role: "assistant", content: "hello", metadata: { id: anchorId } },
|
|
102
|
+
],
|
|
103
|
+
threadMeta: {
|
|
104
|
+
parentMessageSummary: "hello",
|
|
105
|
+
snapshotLength: 2,
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
expect(thread.parentMessageId).toBe(anchorId);
|
|
109
|
+
expect(thread.threadMeta?.snapshotLength).toBe(2);
|
|
110
|
+
|
|
111
|
+
// Summary surfaces the column
|
|
112
|
+
const summary = (await engine.conversations.list("o")).find(
|
|
113
|
+
(s) => s.conversationId === thread.conversationId,
|
|
114
|
+
);
|
|
115
|
+
expect(summary?.parentMessageId).toBe(anchorId);
|
|
116
|
+
|
|
117
|
+
// get() round-trips threadMeta from the JSON blob
|
|
118
|
+
const reloaded = await engine.conversations.get(thread.conversationId);
|
|
119
|
+
expect(reloaded?.parentMessageId).toBe(anchorId);
|
|
120
|
+
expect(reloaded?.threadMeta?.parentMessageSummary).toBe("hello");
|
|
121
|
+
|
|
122
|
+
// listThreads filters to children with parent_message_id set
|
|
123
|
+
const threads = await engine.conversations.listThreads(parent.conversationId);
|
|
124
|
+
expect(threads.length).toBe(1);
|
|
125
|
+
expect(threads[0].conversationId).toBe(thread.conversationId);
|
|
126
|
+
expect(threads[0].parentMessageId).toBe(anchorId);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("listThreads excludes subagent-only children (no parentMessageId)", async () => {
|
|
130
|
+
const parent = await engine.conversations.create("o", "Parent");
|
|
131
|
+
// Subagent: parentConversationId set but no parentMessageId
|
|
132
|
+
await engine.conversations.create("o", "Subagent", null, {
|
|
133
|
+
parentConversationId: parent.conversationId,
|
|
134
|
+
subagentMeta: { task: "x", status: "completed" },
|
|
135
|
+
});
|
|
136
|
+
// Thread: both set
|
|
137
|
+
const thread = await engine.conversations.create("o", "Thread", null, {
|
|
138
|
+
parentConversationId: parent.conversationId,
|
|
139
|
+
parentMessageId: "anchor",
|
|
140
|
+
threadMeta: { snapshotLength: 1 },
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const threads = await engine.conversations.listThreads(parent.conversationId);
|
|
144
|
+
expect(threads).toHaveLength(1);
|
|
145
|
+
expect(threads[0].conversationId).toBe(thread.conversationId);
|
|
146
|
+
});
|
|
67
147
|
});
|
|
68
148
|
|
|
69
149
|
// -- Memory --
|