@deepagents/context 3.1.0 → 4.0.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/README.md +46 -13
- package/dist/browser.js +30 -56
- package/dist/browser.js.map +3 -3
- package/dist/index.js +2359 -2384
- package/dist/index.js.map +4 -4
- package/dist/lib/chain-summary.d.ts.map +1 -1
- package/dist/lib/engine.d.ts.map +1 -1
- package/dist/lib/fragments/message/user.d.ts +42 -85
- package/dist/lib/fragments/message/user.d.ts.map +1 -1
- package/dist/lib/sandbox/agent-os-sandbox.d.ts.map +1 -1
- package/dist/lib/sandbox/bash-tool.d.ts +9 -28
- package/dist/lib/sandbox/bash-tool.d.ts.map +1 -1
- package/dist/lib/sandbox/daytona-sandbox.d.ts.map +1 -1
- package/dist/lib/sandbox/docker-sandbox.d.ts +29 -0
- package/dist/lib/sandbox/docker-sandbox.d.ts.map +1 -1
- package/dist/lib/sandbox/index.d.ts +2 -1
- package/dist/lib/sandbox/index.d.ts.map +1 -1
- package/dist/lib/sandbox/installers/bin.d.ts.map +1 -1
- package/dist/lib/sandbox/installers/index.d.ts +7 -7
- package/dist/lib/sandbox/installers/index.d.ts.map +1 -1
- package/dist/lib/sandbox/installers/installer.d.ts +0 -5
- package/dist/lib/sandbox/installers/installer.d.ts.map +1 -1
- package/dist/lib/sandbox/installers/url-binary.d.ts.map +1 -1
- package/dist/lib/sandbox/shell-quote.d.ts +10 -0
- package/dist/lib/sandbox/shell-quote.d.ts.map +1 -0
- package/dist/lib/sandbox/strace/file-change.d.ts +21 -0
- package/dist/lib/sandbox/strace/file-change.d.ts.map +1 -0
- package/dist/lib/sandbox/strace/file-changes.d.ts +66 -0
- package/dist/lib/sandbox/strace/file-changes.d.ts.map +1 -0
- package/dist/lib/sandbox/strace/index.d.ts +89 -0
- package/dist/lib/sandbox/strace/index.d.ts.map +1 -0
- package/dist/lib/sandbox/strace/index.js +285 -0
- package/dist/lib/sandbox/strace/index.js.map +7 -0
- package/dist/lib/sandbox/types.d.ts +6 -1
- package/dist/lib/sandbox/types.d.ts.map +1 -1
- package/dist/lib/sandbox/virtual-sandbox.d.ts.map +1 -1
- package/dist/lib/save/save-pipeline.d.ts +1 -13
- package/dist/lib/save/save-pipeline.d.ts.map +1 -1
- package/dist/lib/skills/skill-reminder.d.ts +2 -2
- package/dist/lib/skills/skill-reminder.d.ts.map +1 -1
- package/package.json +7 -2
- package/dist/lib/sandbox/file-changes.d.ts +0 -83
- package/dist/lib/sandbox/file-changes.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -49,26 +49,59 @@ deletes the underlying Daytona sandbox.
|
|
|
49
49
|
|
|
50
50
|
### File-change tracking
|
|
51
51
|
|
|
52
|
-
`
|
|
52
|
+
`withStraceFileChanges()` decorates a real sandbox backend so each command,
|
|
53
|
+
spawn, or file write reports the mutations it caused as a `FileChange[]`
|
|
53
54
|
(`{ op: 'write' | 'delete' | 'rename'; path; from?; timestamp }`).
|
|
54
|
-
Consume
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
Consume changes via the `onFileChanges` callback (fires per command, spawn, or
|
|
56
|
+
`writeFiles` call). Bash tool calls also receive
|
|
57
|
+
`tool-result.output.meta.fileChanges` as hidden host-only metadata.
|
|
58
|
+
|
|
59
|
+
Scope which paths are reported with `include` glob patterns (required — a path
|
|
60
|
+
must match at least one); drop noise such as uploaded skills with optional
|
|
61
|
+
`exclude` patterns. Both match absolute paths via Node's `path.matchesGlob`.
|
|
57
62
|
|
|
58
63
|
```ts
|
|
59
|
-
const
|
|
60
|
-
|
|
64
|
+
const backend = await createDockerSandbox({ image: 'my-image-with-strace' });
|
|
65
|
+
const tracked = await withStraceFileChanges(backend, {
|
|
66
|
+
include: ['/workspace/**', '/workspace'],
|
|
61
67
|
onFileChanges: (changes) => {
|
|
62
68
|
for (const c of changes) console.log(`${c.op} ${c.path}`);
|
|
63
69
|
},
|
|
64
70
|
});
|
|
71
|
+
const sandbox = await createBashTool({
|
|
72
|
+
sandbox: tracked,
|
|
73
|
+
destination: '/workspace',
|
|
74
|
+
});
|
|
65
75
|
```
|
|
66
76
|
|
|
67
|
-
Tracking
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
77
|
+
Tracking uses `strace` (per `executeCommand` and per `spawn`) when you compose
|
|
78
|
+
the `withStraceFileChanges()` decorator. The decorator itself does **no**
|
|
79
|
+
self-test — it trusts that strace tracing works in the sandbox, because "strace
|
|
80
|
+
works here" is an invariant of the (image + host kernel + seccomp/caps) that is
|
|
81
|
+
constant for the container's lifetime. Re-proving it per composition would re-pay
|
|
82
|
+
several host→container round-trips on every tool call for no new information.
|
|
83
|
+
|
|
84
|
+
Verifying the invariant is the consumer's **once-per-container** responsibility.
|
|
85
|
+
Run the probe once at startup (e.g. a daemon boot gate) via the lean leaf entry:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import { selfTestStrace } from '@deepagents/context/sandbox/strace';
|
|
89
|
+
|
|
90
|
+
// Throws StraceUnavailableError (reason: 'strace-missing' | 'ptrace-blocked' |
|
|
91
|
+
// 'trace-unparseable') with no silent fallback. A DisposableSandbox satisfies
|
|
92
|
+
// the StraceHost shape structurally, so pass a real backend unchanged; an
|
|
93
|
+
// in-process caller implements just { executeCommand, readFile }.
|
|
94
|
+
await selfTestStrace(backend);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The `@deepagents/context/sandbox/strace` subpath is a node-builtins-only bundle
|
|
98
|
+
(probe + parser + `StraceUnavailableError`) with no agent/context-framework
|
|
99
|
+
imports, so a minimal daemon can import it without pulling the whole framework.
|
|
100
|
+
Import `StraceUnavailableError` from this same subpath when catching the probe's
|
|
101
|
+
error (each entry point is bundled independently, so `instanceof` requires the
|
|
102
|
+
class from the same entry).
|
|
103
|
+
|
|
104
|
+
The backend must satisfy, on any non-virtual backend (Docker, Daytona, e2b, ...):
|
|
72
105
|
|
|
73
106
|
1. `strace` installed in the image — `apk add strace` (Alpine) /
|
|
74
107
|
`apt-get install -y strace` (Debian), or `installers: [pkg(['strace'])]` for
|
|
@@ -78,8 +111,8 @@ satisfy, on any non-virtual backend (Docker, Daytona, e2b, …):
|
|
|
78
111
|
garbles the trace, so build the image for the host arch.
|
|
79
112
|
|
|
80
113
|
The **in-process virtual sandbox cannot host strace** (no real processes/ptrace),
|
|
81
|
-
so it is unsupported by `
|
|
82
|
-
container/VM backend.
|
|
114
|
+
so it is unsupported by `withStraceFileChanges()` — `selfTestStrace` hard-fails
|
|
115
|
+
against it. Use a container/VM backend.
|
|
83
116
|
|
|
84
117
|
Ops are intentionally coarse: strace cannot distinguish a new file from an
|
|
85
118
|
overwrite within one command (both are `O_CREAT|O_TRUNC`), so both report
|
package/dist/browser.js
CHANGED
|
@@ -1815,6 +1815,11 @@ function getReminderRanges(metadata) {
|
|
|
1815
1815
|
end: record.end
|
|
1816
1816
|
}));
|
|
1817
1817
|
}
|
|
1818
|
+
function getReminderOnceIds(message2) {
|
|
1819
|
+
const meta = message2.metadata;
|
|
1820
|
+
if (!isRecord(meta) || !Array.isArray(meta.onceIds)) return [];
|
|
1821
|
+
return meta.onceIds.filter((id) => typeof id === "string");
|
|
1822
|
+
}
|
|
1818
1823
|
function getReminderMetadataRecords(metadata) {
|
|
1819
1824
|
const reminders = metadata?.reminders;
|
|
1820
1825
|
if (!Array.isArray(reminders)) return [];
|
|
@@ -1828,27 +1833,6 @@ function normalizeReminderTarget(target) {
|
|
|
1828
1833
|
if (target === "steer") return "steer";
|
|
1829
1834
|
throw new Error(`Unsupported reminder target: ${String(target)}`);
|
|
1830
1835
|
}
|
|
1831
|
-
function isConditionalReminderOptions(options) {
|
|
1832
|
-
return options !== void 0 && "when" in options;
|
|
1833
|
-
}
|
|
1834
|
-
function isPromiseLike(value) {
|
|
1835
|
-
return (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
|
|
1836
|
-
}
|
|
1837
|
-
function normalizeImmediateReminderText(textOrFragment) {
|
|
1838
|
-
if (isFragment(textOrFragment)) {
|
|
1839
|
-
return new XmlRenderer().render([textOrFragment]);
|
|
1840
|
-
}
|
|
1841
|
-
if (typeof textOrFragment === "string") {
|
|
1842
|
-
return textOrFragment;
|
|
1843
|
-
}
|
|
1844
|
-
return (ctx) => {
|
|
1845
|
-
const resolved = textOrFragment(ctx);
|
|
1846
|
-
if (isPromiseLike(resolved)) {
|
|
1847
|
-
throw new Error("Async reminder text requires a when predicate");
|
|
1848
|
-
}
|
|
1849
|
-
return resolved;
|
|
1850
|
-
};
|
|
1851
|
-
}
|
|
1852
1836
|
function normalizeConditionalReminderText(textOrFragment) {
|
|
1853
1837
|
return isFragment(textOrFragment) ? new XmlRenderer().render([textOrFragment]) : textOrFragment;
|
|
1854
1838
|
}
|
|
@@ -2057,54 +2041,32 @@ function mergeReminderMetadata(message2, addedReminders) {
|
|
|
2057
2041
|
function reminder(textOrFragment, options) {
|
|
2058
2042
|
const target = normalizeReminderTarget(options?.target);
|
|
2059
2043
|
const asPart = target === "user" ? options?.asPart ?? false : false;
|
|
2060
|
-
if (
|
|
2061
|
-
const text2 = normalizeConditionalReminderText(textOrFragment);
|
|
2062
|
-
if (typeof text2 === "string") {
|
|
2063
|
-
assertReminderText(text2);
|
|
2064
|
-
}
|
|
2065
|
-
return {
|
|
2066
|
-
name: "reminder",
|
|
2067
|
-
data: null,
|
|
2068
|
-
metadata: {
|
|
2069
|
-
reminder: {
|
|
2070
|
-
text: text2,
|
|
2071
|
-
when: options.when,
|
|
2072
|
-
asPart,
|
|
2073
|
-
target
|
|
2074
|
-
}
|
|
2075
|
-
}
|
|
2076
|
-
};
|
|
2077
|
-
}
|
|
2078
|
-
if (target !== "user") {
|
|
2044
|
+
if (options?.when === void 0 && target !== "user") {
|
|
2079
2045
|
throw new Error(`Reminder target "${target}" requires a when predicate`);
|
|
2080
2046
|
}
|
|
2081
|
-
const text =
|
|
2047
|
+
const text = normalizeConditionalReminderText(textOrFragment);
|
|
2082
2048
|
if (typeof text === "string") {
|
|
2083
2049
|
assertReminderText(text);
|
|
2084
2050
|
}
|
|
2085
2051
|
return {
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2052
|
+
name: "reminder",
|
|
2053
|
+
data: null,
|
|
2054
|
+
metadata: {
|
|
2055
|
+
reminder: {
|
|
2056
|
+
text,
|
|
2057
|
+
when: options?.when ?? (() => true),
|
|
2058
|
+
asPart,
|
|
2059
|
+
target
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2089
2062
|
};
|
|
2090
2063
|
}
|
|
2091
|
-
function user(content
|
|
2064
|
+
function user(content) {
|
|
2092
2065
|
const message2 = typeof content === "string" ? {
|
|
2093
2066
|
id: generateId2(),
|
|
2094
2067
|
role: "user",
|
|
2095
2068
|
parts: [{ type: "text", text: content }]
|
|
2096
2069
|
} : { ...content, role: "user", parts: [...content.parts] };
|
|
2097
|
-
if (reminders.length > 0) {
|
|
2098
|
-
const plainText = extractPlainText(message2);
|
|
2099
|
-
const added = [];
|
|
2100
|
-
for (const item of reminders) {
|
|
2101
|
-
const meta = applyReminderToMessage(message2, item, {
|
|
2102
|
-
content: plainText
|
|
2103
|
-
});
|
|
2104
|
-
if (meta) added.push(meta);
|
|
2105
|
-
}
|
|
2106
|
-
mergeReminderMetadata(message2, added);
|
|
2107
|
-
}
|
|
2108
2070
|
return {
|
|
2109
2071
|
id: message2.id,
|
|
2110
2072
|
name: "user",
|
|
@@ -2120,6 +2082,16 @@ function user(content, ...reminders) {
|
|
|
2120
2082
|
}
|
|
2121
2083
|
};
|
|
2122
2084
|
}
|
|
2085
|
+
function applyUserRemindersToMessage(message2, reminders) {
|
|
2086
|
+
if (reminders.length === 0) return;
|
|
2087
|
+
const plainText = extractPlainText(message2);
|
|
2088
|
+
const added = [];
|
|
2089
|
+
for (const item of reminders) {
|
|
2090
|
+
const meta = applyReminderToMessage(message2, item, { content: plainText });
|
|
2091
|
+
if (meta) added.push(meta);
|
|
2092
|
+
}
|
|
2093
|
+
mergeReminderMetadata(message2, added);
|
|
2094
|
+
}
|
|
2123
2095
|
function synthesizeSteerUserMessage(text, firedAt, onceIds = []) {
|
|
2124
2096
|
const texts = Array.isArray(text) ? text : [text];
|
|
2125
2097
|
for (const value of texts) assertReminderText(value);
|
|
@@ -2388,6 +2360,7 @@ export {
|
|
|
2388
2360
|
applyPartReminder,
|
|
2389
2361
|
applyReminderToMessage,
|
|
2390
2362
|
applyRemindersToToolOutput,
|
|
2363
|
+
applyUserRemindersToMessage,
|
|
2391
2364
|
assistant,
|
|
2392
2365
|
assistantText,
|
|
2393
2366
|
clarification,
|
|
@@ -2402,6 +2375,7 @@ export {
|
|
|
2402
2375
|
fromFragment,
|
|
2403
2376
|
getFragmentData,
|
|
2404
2377
|
getModelsRegistry,
|
|
2378
|
+
getReminderOnceIds,
|
|
2405
2379
|
getReminderRanges,
|
|
2406
2380
|
glossary,
|
|
2407
2381
|
guardrail,
|