@ai-sdk/harness-deepagents 1.0.93 → 1.0.95
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/CHANGELOG.md +21 -0
- package/dist/bridge/index.mjs +160 -22
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.js +23 -32
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/bridge/index.ts +49 -28
- package/src/bridge/persistent-memory-saver.ts +137 -0
- package/src/deepagents-bootstrap.ts +19 -15
- package/src/deepagents-harness.ts +9 -21
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @ai-sdk/harness-deepagents
|
|
2
2
|
|
|
3
|
+
## 1.0.95
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 371e954: feat(harness): add `createBridgeToken()` and `withBridgeToken()` helpers for bridge backed harness adapters
|
|
8
|
+
- 62f481f: fix(harness): fix bridge resolution to no longer look for an alternative path which could cause Turbopack errors
|
|
9
|
+
- Updated dependencies [371e954]
|
|
10
|
+
- Updated dependencies [87b4858]
|
|
11
|
+
- @ai-sdk/harness@1.0.95
|
|
12
|
+
|
|
13
|
+
## 1.0.94
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- 9ec34bd: Preserve Deep Agents conversation context when a stopped session is resumed.
|
|
18
|
+
- 8961fde: feat(harness): allow changing `model` between turns via call options
|
|
19
|
+
- Updated dependencies [8961fde]
|
|
20
|
+
- Updated dependencies [eb59f2a]
|
|
21
|
+
- @ai-sdk/harness@1.0.94
|
|
22
|
+
- @ai-sdk/provider-utils@5.0.34
|
|
23
|
+
|
|
3
24
|
## 1.0.93
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/dist/bridge/index.mjs
CHANGED
|
@@ -1892,6 +1892,124 @@ function createLocalShellBackend({
|
|
|
1892
1892
|
});
|
|
1893
1893
|
}
|
|
1894
1894
|
|
|
1895
|
+
// src/bridge/persistent-memory-saver.ts
|
|
1896
|
+
import { mkdir as mkdir2, readFile, rename, rm, writeFile as writeFile2 } from "fs/promises";
|
|
1897
|
+
import { dirname } from "path";
|
|
1898
|
+
var SNAPSHOT_HEADER = "deepagents-memory-saver-v1";
|
|
1899
|
+
function encodeString(value) {
|
|
1900
|
+
return Buffer.from(value, "utf8").toString("base64");
|
|
1901
|
+
}
|
|
1902
|
+
function decodeString(value) {
|
|
1903
|
+
return Buffer.from(value, "base64").toString("utf8");
|
|
1904
|
+
}
|
|
1905
|
+
function encodeBytes(value) {
|
|
1906
|
+
return Buffer.from(value).toString("base64");
|
|
1907
|
+
}
|
|
1908
|
+
function decodeBytes(value) {
|
|
1909
|
+
return Buffer.from(value, "base64");
|
|
1910
|
+
}
|
|
1911
|
+
async function loadMemorySaver({
|
|
1912
|
+
path,
|
|
1913
|
+
saver
|
|
1914
|
+
}) {
|
|
1915
|
+
let snapshot;
|
|
1916
|
+
try {
|
|
1917
|
+
snapshot = await readFile(path, "utf8");
|
|
1918
|
+
} catch (error) {
|
|
1919
|
+
if (error.code === "ENOENT") return;
|
|
1920
|
+
throw error;
|
|
1921
|
+
}
|
|
1922
|
+
const [header, ...lines] = snapshot.split("\n");
|
|
1923
|
+
if (header !== SNAPSHOT_HEADER) {
|
|
1924
|
+
throw new Error("Unsupported Deep Agents conversation checkpoint format");
|
|
1925
|
+
}
|
|
1926
|
+
const storage = /* @__PURE__ */ Object.create(null);
|
|
1927
|
+
const writes = /* @__PURE__ */ Object.create(null);
|
|
1928
|
+
for (const line of lines) {
|
|
1929
|
+
if (line === "") continue;
|
|
1930
|
+
const fields = line.split(" ");
|
|
1931
|
+
if (fields[0] === "S" && fields.length === 7) {
|
|
1932
|
+
const [, threadIdValue, namespaceValue, checkpointIdValue] = fields;
|
|
1933
|
+
const threadId = decodeString(threadIdValue);
|
|
1934
|
+
const namespace = decodeString(namespaceValue);
|
|
1935
|
+
const checkpointId = decodeString(checkpointIdValue);
|
|
1936
|
+
storage[threadId] ??= /* @__PURE__ */ Object.create(null);
|
|
1937
|
+
storage[threadId][namespace] ??= /* @__PURE__ */ Object.create(null);
|
|
1938
|
+
storage[threadId][namespace][checkpointId] = [
|
|
1939
|
+
decodeBytes(fields[4]),
|
|
1940
|
+
decodeBytes(fields[5]),
|
|
1941
|
+
fields[6] === "" ? void 0 : decodeString(fields[6])
|
|
1942
|
+
];
|
|
1943
|
+
continue;
|
|
1944
|
+
}
|
|
1945
|
+
if (fields[0] === "W" && fields.length === 6) {
|
|
1946
|
+
const [, keyValue, indexValue, taskIdValue, channelValue, value] = fields;
|
|
1947
|
+
const key = decodeString(keyValue);
|
|
1948
|
+
const index = decodeString(indexValue);
|
|
1949
|
+
writes[key] ??= /* @__PURE__ */ Object.create(null);
|
|
1950
|
+
writes[key][index] = [
|
|
1951
|
+
decodeString(taskIdValue),
|
|
1952
|
+
decodeString(channelValue),
|
|
1953
|
+
decodeBytes(value)
|
|
1954
|
+
];
|
|
1955
|
+
continue;
|
|
1956
|
+
}
|
|
1957
|
+
throw new Error("Invalid Deep Agents conversation checkpoint");
|
|
1958
|
+
}
|
|
1959
|
+
saver.storage = storage;
|
|
1960
|
+
saver.writes = writes;
|
|
1961
|
+
}
|
|
1962
|
+
async function saveMemorySaver({
|
|
1963
|
+
path,
|
|
1964
|
+
saver
|
|
1965
|
+
}) {
|
|
1966
|
+
const lines = [SNAPSHOT_HEADER];
|
|
1967
|
+
for (const [threadId, namespaces] of Object.entries(saver.storage)) {
|
|
1968
|
+
for (const [namespace, checkpoints] of Object.entries(namespaces)) {
|
|
1969
|
+
for (const [
|
|
1970
|
+
checkpointId,
|
|
1971
|
+
[checkpoint, metadata, parentCheckpointId]
|
|
1972
|
+
] of Object.entries(checkpoints)) {
|
|
1973
|
+
lines.push(
|
|
1974
|
+
[
|
|
1975
|
+
"S",
|
|
1976
|
+
encodeString(threadId),
|
|
1977
|
+
encodeString(namespace),
|
|
1978
|
+
encodeString(checkpointId),
|
|
1979
|
+
encodeBytes(checkpoint),
|
|
1980
|
+
encodeBytes(metadata),
|
|
1981
|
+
parentCheckpointId == null ? "" : encodeString(parentCheckpointId)
|
|
1982
|
+
].join(" ")
|
|
1983
|
+
);
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
for (const [key, indexedWrites] of Object.entries(saver.writes)) {
|
|
1988
|
+
for (const [index, [taskId, channel, value]] of Object.entries(
|
|
1989
|
+
indexedWrites
|
|
1990
|
+
)) {
|
|
1991
|
+
lines.push(
|
|
1992
|
+
[
|
|
1993
|
+
"W",
|
|
1994
|
+
encodeString(key),
|
|
1995
|
+
encodeString(index),
|
|
1996
|
+
encodeString(taskId),
|
|
1997
|
+
encodeString(channel),
|
|
1998
|
+
encodeBytes(value)
|
|
1999
|
+
].join(" ")
|
|
2000
|
+
);
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
await mkdir2(dirname(path), { recursive: true });
|
|
2004
|
+
const temporaryPath = `${path}.${process.pid}.tmp`;
|
|
2005
|
+
await writeFile2(temporaryPath, `${lines.join("\n")}
|
|
2006
|
+
`, "utf8");
|
|
2007
|
+
await rename(temporaryPath, path);
|
|
2008
|
+
}
|
|
2009
|
+
async function removeMemorySaverSnapshot(path) {
|
|
2010
|
+
await rm(path, { force: true });
|
|
2011
|
+
}
|
|
2012
|
+
|
|
1895
2013
|
// src/bridge/tool-filtering.ts
|
|
1896
2014
|
import {
|
|
1897
2015
|
AIMessage as AIMessage18,
|
|
@@ -2008,14 +2126,22 @@ function buildModel({
|
|
|
2008
2126
|
} : {}
|
|
2009
2127
|
});
|
|
2010
2128
|
}
|
|
2011
|
-
function
|
|
2012
|
-
thinking,
|
|
2013
|
-
effort
|
|
2014
|
-
}) {
|
|
2015
|
-
if (!thinking && !effort) return void 0;
|
|
2129
|
+
function createModelMiddleware() {
|
|
2016
2130
|
return createMiddleware({
|
|
2017
|
-
name: "
|
|
2131
|
+
name: "harnessModel",
|
|
2018
2132
|
wrapModelCall: async (request, handler) => {
|
|
2133
|
+
if (!activeModel && !activeThinking && !activeEffort) {
|
|
2134
|
+
return handler(request);
|
|
2135
|
+
}
|
|
2136
|
+
if (activeModel) {
|
|
2137
|
+
const configuredModel2 = buildModel({
|
|
2138
|
+
rawModel: activeModel,
|
|
2139
|
+
thinking: activeThinking,
|
|
2140
|
+
effort: activeEffort
|
|
2141
|
+
});
|
|
2142
|
+
if (!configuredModel2) throw new Error("Deep Agents model is missing");
|
|
2143
|
+
return handler({ ...request, model: configuredModel2 });
|
|
2144
|
+
}
|
|
2019
2145
|
let model = request.model;
|
|
2020
2146
|
if ("_getModelInstance" in model && typeof model._getModelInstance === "function") {
|
|
2021
2147
|
model = await model._getModelInstance();
|
|
@@ -2025,8 +2151,8 @@ function createReasoningMiddleware({
|
|
|
2025
2151
|
}
|
|
2026
2152
|
const configuredModel = buildModel({
|
|
2027
2153
|
rawModel: model.model,
|
|
2028
|
-
thinking,
|
|
2029
|
-
effort
|
|
2154
|
+
thinking: activeThinking,
|
|
2155
|
+
effort: activeEffort
|
|
2030
2156
|
});
|
|
2031
2157
|
if (!configuredModel) throw new Error("Deep Agents model is missing");
|
|
2032
2158
|
return handler({ ...request, model: configuredModel });
|
|
@@ -2040,13 +2166,26 @@ if (!workdir || !bridgeStateDir) {
|
|
|
2040
2166
|
console.error("deepagents bridge: missing --workdir / --bridge-state-dir");
|
|
2041
2167
|
process.exit(1);
|
|
2042
2168
|
}
|
|
2169
|
+
var conversationCheckpointPath = `${bridgeStateDir}/conversation.checkpoint`;
|
|
2043
2170
|
var agent;
|
|
2044
2171
|
var currentTurn;
|
|
2045
2172
|
var mcpClient;
|
|
2046
2173
|
var mcpToolNames = /* @__PURE__ */ new Set();
|
|
2047
2174
|
var currentResponseFormat;
|
|
2048
2175
|
var checkpointer = new MemorySaver2();
|
|
2176
|
+
if (args.resume === "true") {
|
|
2177
|
+
await loadMemorySaver({
|
|
2178
|
+
path: conversationCheckpointPath,
|
|
2179
|
+
saver: checkpointer
|
|
2180
|
+
});
|
|
2181
|
+
} else {
|
|
2182
|
+
await removeMemorySaverSnapshot(conversationCheckpointPath);
|
|
2183
|
+
}
|
|
2049
2184
|
var agentConfigurationSignature;
|
|
2185
|
+
var activeModel;
|
|
2186
|
+
var activeThinking;
|
|
2187
|
+
var activeEffort;
|
|
2188
|
+
var modelMiddleware = createModelMiddleware();
|
|
2050
2189
|
var responseFormatMiddleware = createMiddleware({
|
|
2051
2190
|
name: "HarnessResponseFormat",
|
|
2052
2191
|
wrapModelCall(request, handler) {
|
|
@@ -2083,6 +2222,9 @@ function buildHostTools(toolSchemas) {
|
|
|
2083
2222
|
}
|
|
2084
2223
|
async function runTurn(start, turn) {
|
|
2085
2224
|
currentTurn = turn;
|
|
2225
|
+
if (start.model) activeModel = start.model;
|
|
2226
|
+
activeThinking = start.thinking;
|
|
2227
|
+
activeEffort = start.effort;
|
|
2086
2228
|
currentResponseFormat = start.responseFormat?.type === "json" && start.responseFormat.schema != null ? toolStrategy(start.responseFormat.schema) : void 0;
|
|
2087
2229
|
const emit = (event) => turn.emit(event);
|
|
2088
2230
|
const interruptOn = buildInterruptOn(
|
|
@@ -2108,15 +2250,6 @@ async function runTurn(start, turn) {
|
|
|
2108
2250
|
});
|
|
2109
2251
|
}
|
|
2110
2252
|
await closeMcpClient();
|
|
2111
|
-
const model = buildModel({
|
|
2112
|
-
rawModel: start.model,
|
|
2113
|
-
thinking: start.thinking,
|
|
2114
|
-
effort: start.effort
|
|
2115
|
-
});
|
|
2116
|
-
const reasoningMiddleware = model ? void 0 : createReasoningMiddleware({
|
|
2117
|
-
thinking: start.thinking,
|
|
2118
|
-
effort: start.effort
|
|
2119
|
-
});
|
|
2120
2253
|
const builtinToolFilteringMiddleware = createBuiltinToolFilteringMiddleware(
|
|
2121
2254
|
{
|
|
2122
2255
|
builtinToolFiltering: start.builtinToolFiltering,
|
|
@@ -2129,7 +2262,7 @@ async function runTurn(start, turn) {
|
|
|
2129
2262
|
);
|
|
2130
2263
|
const middleware = [
|
|
2131
2264
|
responseFormatMiddleware,
|
|
2132
|
-
|
|
2265
|
+
modelMiddleware,
|
|
2133
2266
|
...builtinToolFilteringMiddleware ? [builtinToolFilteringMiddleware] : []
|
|
2134
2267
|
];
|
|
2135
2268
|
const hostTools = buildHostTools(start.tools);
|
|
@@ -2142,8 +2275,6 @@ async function runTurn(start, turn) {
|
|
|
2142
2275
|
);
|
|
2143
2276
|
mcpToolNames = new Set(mcpTools.map((mcpTool) => mcpTool.name));
|
|
2144
2277
|
agent = createDeepAgent({
|
|
2145
|
-
// Defer to Deep Agents's own default when the host configured no model.
|
|
2146
|
-
...model ? { model } : {},
|
|
2147
2278
|
tools: [...mcpTools, ...hostTools],
|
|
2148
2279
|
backend: createLocalShellBackend({ rootDir: workdir }),
|
|
2149
2280
|
systemPrompt: start.instructions ? { suffix: start.instructions } : void 0,
|
|
@@ -2165,7 +2296,7 @@ async function runTurn(start, turn) {
|
|
|
2165
2296
|
const streamEventState = createDeepAgentsStreamEventState();
|
|
2166
2297
|
const emitStreamEvent = createEmitStreamEvent({
|
|
2167
2298
|
state: streamEventState,
|
|
2168
|
-
configuredModel:
|
|
2299
|
+
configuredModel: activeModel,
|
|
2169
2300
|
hostToolNames,
|
|
2170
2301
|
mcpToolNames,
|
|
2171
2302
|
structuredOutputToolNames: new Set(
|
|
@@ -2268,9 +2399,16 @@ await runBridge({
|
|
|
2268
2399
|
onStart: runTurn,
|
|
2269
2400
|
onStop: async () => {
|
|
2270
2401
|
await closeMcpClient();
|
|
2402
|
+
await saveMemorySaver({
|
|
2403
|
+
path: conversationCheckpointPath,
|
|
2404
|
+
saver: checkpointer
|
|
2405
|
+
});
|
|
2271
2406
|
return {};
|
|
2272
2407
|
},
|
|
2273
|
-
onDestroy:
|
|
2408
|
+
onDestroy: async () => {
|
|
2409
|
+
await closeMcpClient();
|
|
2410
|
+
await removeMemorySaverSnapshot(conversationCheckpointPath);
|
|
2411
|
+
}
|
|
2274
2412
|
});
|
|
2275
2413
|
async function loadMcpTools({
|
|
2276
2414
|
mcpServers
|