@deepagents/context 0.30.0 → 0.32.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/dist/browser.js +41 -7
- package/dist/browser.js.map +2 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +478 -73
- package/dist/index.js.map +4 -4
- package/dist/lib/engine.d.ts +0 -6
- package/dist/lib/engine.d.ts.map +1 -1
- package/dist/lib/fragments/message/environment-reminder.d.ts +26 -0
- package/dist/lib/fragments/message/environment-reminder.d.ts.map +1 -0
- package/dist/lib/fragments/message/user.d.ts +15 -1
- package/dist/lib/fragments/message/user.d.ts.map +1 -1
- package/dist/lib/fragments/socratic.d.ts +21 -0
- package/dist/lib/fragments/socratic.d.ts.map +1 -0
- package/dist/lib/sandbox/agent-os-sandbox.d.ts +84 -0
- package/dist/lib/sandbox/agent-os-sandbox.d.ts.map +1 -0
- package/dist/lib/sandbox/container-tool.d.ts +3 -1
- package/dist/lib/sandbox/container-tool.d.ts.map +1 -1
- package/dist/lib/sandbox/docker-sandbox.d.ts +8 -3
- 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/tracing/batch-processor.d.ts +19 -0
- package/dist/lib/tracing/batch-processor.d.ts.map +1 -0
- package/dist/lib/tracing/exporter.d.ts +22 -0
- package/dist/lib/tracing/exporter.d.ts.map +1 -0
- package/dist/lib/tracing/ids.d.ts +4 -0
- package/dist/lib/tracing/ids.d.ts.map +1 -0
- package/dist/lib/tracing/index.d.ts +7 -0
- package/dist/lib/tracing/index.d.ts.map +1 -0
- package/dist/lib/tracing/index.js +661 -0
- package/dist/lib/tracing/index.js.map +7 -0
- package/dist/lib/tracing/openai-traces-integration.d.ts +20 -0
- package/dist/lib/tracing/openai-traces-integration.d.ts.map +1 -0
- package/dist/lib/tracing/processor.d.ts +26 -0
- package/dist/lib/tracing/processor.d.ts.map +1 -0
- package/dist/lib/tracing/serialization.d.ts +7 -0
- package/dist/lib/tracing/serialization.d.ts.map +1 -0
- package/dist/lib/tracing/types.d.ts +90 -0
- package/dist/lib/tracing/types.d.ts.map +1 -0
- package/package.json +18 -5
package/dist/index.js
CHANGED
|
@@ -426,7 +426,7 @@ import {
|
|
|
426
426
|
import { z } from "zod";
|
|
427
427
|
|
|
428
428
|
// packages/context/src/lib/engine.ts
|
|
429
|
-
import {
|
|
429
|
+
import { validateUIMessages } from "ai";
|
|
430
430
|
import { mergeWith } from "lodash-es";
|
|
431
431
|
|
|
432
432
|
// packages/context/src/lib/estimate.ts
|
|
@@ -753,14 +753,45 @@ function applyPartReminder(message2, value) {
|
|
|
753
753
|
};
|
|
754
754
|
}
|
|
755
755
|
function resolveReminderText(item, ctx) {
|
|
756
|
-
return
|
|
756
|
+
return resolveReminder(item, ctx)?.text ?? "";
|
|
757
|
+
}
|
|
758
|
+
function normalizeReminderResolution(value) {
|
|
759
|
+
if (typeof value === "string") {
|
|
760
|
+
return value.trim().length === 0 ? null : { text: value };
|
|
761
|
+
}
|
|
762
|
+
if (value.text.trim().length === 0) {
|
|
763
|
+
return null;
|
|
764
|
+
}
|
|
765
|
+
return value;
|
|
766
|
+
}
|
|
767
|
+
function resolveReminder(item, ctx) {
|
|
768
|
+
const resolvedText = typeof item.text === "function" ? item.text(ctx) : item.text;
|
|
769
|
+
const resolved = normalizeReminderResolution(resolvedText);
|
|
770
|
+
if (!resolved) {
|
|
771
|
+
return null;
|
|
772
|
+
}
|
|
773
|
+
const metadata = item.metadata || resolved.metadata ? {
|
|
774
|
+
...item.metadata ?? {},
|
|
775
|
+
...resolved.metadata ?? {}
|
|
776
|
+
} : void 0;
|
|
777
|
+
return metadata ? { ...resolved, metadata } : resolved;
|
|
778
|
+
}
|
|
779
|
+
function mergeMessageMetadata(message2, addedMetadata) {
|
|
780
|
+
if (Object.keys(addedMetadata).length === 0) {
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
const metadata = isRecord(message2.metadata) ? { ...message2.metadata } : {};
|
|
784
|
+
message2.metadata = { ...metadata, ...addedMetadata };
|
|
757
785
|
}
|
|
758
786
|
function applyReminderToMessage(message2, item, ctx) {
|
|
759
|
-
const
|
|
760
|
-
if (
|
|
787
|
+
const resolved = resolveReminder(item, ctx);
|
|
788
|
+
if (!resolved) {
|
|
761
789
|
return null;
|
|
762
790
|
}
|
|
763
|
-
|
|
791
|
+
if (resolved.metadata) {
|
|
792
|
+
mergeMessageMetadata(message2, resolved.metadata);
|
|
793
|
+
}
|
|
794
|
+
return item.asPart ? applyPartReminder(message2, resolved.text) : applyInlineReminder(message2, resolved.text);
|
|
764
795
|
}
|
|
765
796
|
function mergeReminderMetadata(message2, addedReminders) {
|
|
766
797
|
if (addedReminders.length === 0) return;
|
|
@@ -798,14 +829,14 @@ function user(content, ...reminders) {
|
|
|
798
829
|
} : { ...content, role: "user", parts: [...content.parts] };
|
|
799
830
|
if (reminders.length > 0) {
|
|
800
831
|
const plainText = extractPlainText(message2);
|
|
801
|
-
const
|
|
832
|
+
const added = [];
|
|
802
833
|
for (const item of reminders) {
|
|
803
834
|
const meta = applyReminderToMessage(message2, item, {
|
|
804
835
|
content: plainText
|
|
805
836
|
});
|
|
806
|
-
if (meta)
|
|
837
|
+
if (meta) added.push(meta);
|
|
807
838
|
}
|
|
808
|
-
mergeReminderMetadata(message2,
|
|
839
|
+
mergeReminderMetadata(message2, added);
|
|
809
840
|
}
|
|
810
841
|
return {
|
|
811
842
|
id: message2.id,
|
|
@@ -1721,6 +1752,14 @@ var ContextEngine = class {
|
|
|
1721
1752
|
#initialized = false;
|
|
1722
1753
|
/** Initial metadata to merge on first initialization */
|
|
1723
1754
|
#initialMetadata;
|
|
1755
|
+
get #activeBranch() {
|
|
1756
|
+
if (!this.#branch) {
|
|
1757
|
+
throw new Error(
|
|
1758
|
+
"Branch not initialized. Call #ensureInitialized() first."
|
|
1759
|
+
);
|
|
1760
|
+
}
|
|
1761
|
+
return this.#branch;
|
|
1762
|
+
}
|
|
1724
1763
|
get #renderableFragments() {
|
|
1725
1764
|
return this.#fragments.filter((f) => !isConditionalReminder(f));
|
|
1726
1765
|
}
|
|
@@ -1757,7 +1796,13 @@ var ContextEngine = class {
|
|
|
1757
1796
|
});
|
|
1758
1797
|
this.#initialMetadata = void 0;
|
|
1759
1798
|
}
|
|
1760
|
-
|
|
1799
|
+
const branch = await this.#store.getActiveBranch(this.#chatId);
|
|
1800
|
+
if (!branch) {
|
|
1801
|
+
throw new Error(
|
|
1802
|
+
`Active branch not found for chat "${this.#chatId}" after upsertChat`
|
|
1803
|
+
);
|
|
1804
|
+
}
|
|
1805
|
+
this.#branch = branch;
|
|
1761
1806
|
this.#initialized = true;
|
|
1762
1807
|
}
|
|
1763
1808
|
/**
|
|
@@ -1841,30 +1886,35 @@ var ContextEngine = class {
|
|
|
1841
1886
|
};
|
|
1842
1887
|
}
|
|
1843
1888
|
/**
|
|
1844
|
-
* Count user
|
|
1845
|
-
* Includes persisted messages and pending messages.
|
|
1846
|
-
* A turn is one user message paired with one assistant message.
|
|
1847
|
-
* An unpaired trailing user message counts as the next turn.
|
|
1889
|
+
* Count user turns in the conversation and return the previous saved user message context.
|
|
1890
|
+
* Includes persisted messages and pending messages in the turn count.
|
|
1848
1891
|
*/
|
|
1849
|
-
async
|
|
1892
|
+
async #getChainContext() {
|
|
1850
1893
|
await this.#ensureInitialized();
|
|
1851
|
-
let
|
|
1894
|
+
let turn = 0;
|
|
1895
|
+
let lastMessageAt;
|
|
1896
|
+
let lastMessage;
|
|
1852
1897
|
if (this.#branch?.headMessageId) {
|
|
1853
1898
|
const chain = await this.#store.getMessageChain(
|
|
1854
1899
|
this.#branch.headMessageId
|
|
1855
1900
|
);
|
|
1856
1901
|
for (const msg of chain) {
|
|
1857
|
-
if (msg.name
|
|
1858
|
-
|
|
1902
|
+
if (msg.name !== "user") {
|
|
1903
|
+
continue;
|
|
1859
1904
|
}
|
|
1905
|
+
turn++;
|
|
1906
|
+
lastMessageAt = msg.createdAt;
|
|
1907
|
+
lastMessage = msg.data;
|
|
1860
1908
|
}
|
|
1861
1909
|
}
|
|
1862
1910
|
for (const fragment2 of this.#pendingMessages) {
|
|
1863
|
-
if (fragment2.name === "user")
|
|
1864
|
-
userCount++;
|
|
1865
|
-
}
|
|
1911
|
+
if (fragment2.name === "user") turn++;
|
|
1866
1912
|
}
|
|
1867
|
-
return
|
|
1913
|
+
return { turn, lastMessageAt, lastMessage };
|
|
1914
|
+
}
|
|
1915
|
+
async getTurnCount() {
|
|
1916
|
+
const { turn } = await this.#getChainContext();
|
|
1917
|
+
return turn;
|
|
1868
1918
|
}
|
|
1869
1919
|
/**
|
|
1870
1920
|
* Add fragments to the context.
|
|
@@ -1935,37 +1985,6 @@ var ContextEngine = class {
|
|
|
1935
1985
|
}
|
|
1936
1986
|
messages.push(fragment2.codec.encode());
|
|
1937
1987
|
}
|
|
1938
|
-
const conditionalReminders = this.#fragments.filter(isConditionalReminder);
|
|
1939
|
-
if (conditionalReminders.length > 0) {
|
|
1940
|
-
const turn = await this.getTurnCount();
|
|
1941
|
-
let lastUserIndex = -1;
|
|
1942
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1943
|
-
if (messages[i].role === "user") {
|
|
1944
|
-
lastUserIndex = i;
|
|
1945
|
-
break;
|
|
1946
|
-
}
|
|
1947
|
-
}
|
|
1948
|
-
if (lastUserIndex >= 0) {
|
|
1949
|
-
const original = messages[lastUserIndex];
|
|
1950
|
-
const message2 = {
|
|
1951
|
-
...original,
|
|
1952
|
-
parts: [...original.parts]
|
|
1953
|
-
};
|
|
1954
|
-
const plainText = message2.parts.filter(isTextUIPart2).map((p) => p.text).join(" ");
|
|
1955
|
-
const addedReminders = [];
|
|
1956
|
-
for (const fragment2 of conditionalReminders) {
|
|
1957
|
-
const config = getConditionalReminder(fragment2);
|
|
1958
|
-
if (!config.when(turn)) continue;
|
|
1959
|
-
const meta = applyReminderToMessage(message2, config, {
|
|
1960
|
-
content: plainText,
|
|
1961
|
-
turn
|
|
1962
|
-
});
|
|
1963
|
-
if (meta) addedReminders.push(meta);
|
|
1964
|
-
}
|
|
1965
|
-
mergeReminderMetadata(message2, addedReminders);
|
|
1966
|
-
messages[lastUserIndex] = message2;
|
|
1967
|
-
}
|
|
1968
|
-
}
|
|
1969
1988
|
return {
|
|
1970
1989
|
systemPrompt,
|
|
1971
1990
|
messages: messages.length === 0 ? [] : await validateUIMessages({ messages })
|
|
@@ -2009,7 +2028,49 @@ var ContextEngine = class {
|
|
|
2009
2028
|
}
|
|
2010
2029
|
}
|
|
2011
2030
|
}
|
|
2012
|
-
|
|
2031
|
+
const conditionalReminders = this.#fragments.filter(isConditionalReminder);
|
|
2032
|
+
if (conditionalReminders.length > 0) {
|
|
2033
|
+
let lastUserIndex = -1;
|
|
2034
|
+
for (let i = this.#pendingMessages.length - 1; i >= 0; i--) {
|
|
2035
|
+
if (this.#pendingMessages[i].name === "user") {
|
|
2036
|
+
lastUserIndex = i;
|
|
2037
|
+
break;
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
if (lastUserIndex >= 0) {
|
|
2041
|
+
const lastUserFragment = this.#pendingMessages[lastUserIndex];
|
|
2042
|
+
if (lastUserFragment.codec) {
|
|
2043
|
+
const { turn, lastMessageAt, lastMessage } = await this.#getChainContext();
|
|
2044
|
+
const firedReminders = conditionalReminders.map(getConditionalReminder).filter((config) => config.when(turn));
|
|
2045
|
+
if (firedReminders.length > 0) {
|
|
2046
|
+
const original = lastUserFragment.codec.encode();
|
|
2047
|
+
const plainText = extractPlainText(original);
|
|
2048
|
+
const reminders = firedReminders.flatMap((rem) => {
|
|
2049
|
+
const resolved = resolveReminder(rem, {
|
|
2050
|
+
content: plainText,
|
|
2051
|
+
turn,
|
|
2052
|
+
lastMessageAt,
|
|
2053
|
+
lastMessage
|
|
2054
|
+
});
|
|
2055
|
+
if (!resolved) {
|
|
2056
|
+
return [];
|
|
2057
|
+
}
|
|
2058
|
+
return [
|
|
2059
|
+
{
|
|
2060
|
+
text: resolved.text,
|
|
2061
|
+
asPart: rem.asPart,
|
|
2062
|
+
metadata: resolved.metadata
|
|
2063
|
+
}
|
|
2064
|
+
];
|
|
2065
|
+
});
|
|
2066
|
+
const recreated = user(original, ...reminders);
|
|
2067
|
+
recreated.id = lastUserFragment.id;
|
|
2068
|
+
this.#pendingMessages[lastUserIndex] = recreated;
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
let parentId = this.#activeBranch.headMessageId;
|
|
2013
2074
|
const now = Date.now();
|
|
2014
2075
|
for (const fragment2 of this.#pendingMessages) {
|
|
2015
2076
|
if (!fragment2.codec) {
|
|
@@ -2037,10 +2098,10 @@ var ContextEngine = class {
|
|
|
2037
2098
|
await this.#store.addMessage(messageData);
|
|
2038
2099
|
parentId = messageData.id;
|
|
2039
2100
|
}
|
|
2040
|
-
await this.#store.updateBranchHead(this.#
|
|
2041
|
-
this.#
|
|
2101
|
+
await this.#store.updateBranchHead(this.#activeBranch.id, parentId);
|
|
2102
|
+
this.#activeBranch.headMessageId = parentId;
|
|
2042
2103
|
this.#pendingMessages = [];
|
|
2043
|
-
return { headMessageId: this.#
|
|
2104
|
+
return { headMessageId: this.#activeBranch.headMessageId ?? void 0 };
|
|
2044
2105
|
}
|
|
2045
2106
|
/**
|
|
2046
2107
|
* Resolve a lazy fragment by finding the appropriate ID.
|
|
@@ -3814,6 +3875,159 @@ function fromFragment(fragment2, options) {
|
|
|
3814
3875
|
throw new Error(`Fragment "${fragment2.name}" is missing codec`);
|
|
3815
3876
|
}
|
|
3816
3877
|
|
|
3878
|
+
// packages/context/src/lib/fragments/message/environment-reminder.ts
|
|
3879
|
+
var ENVIRONMENT_REMINDER_METADATA_KEY = "environment";
|
|
3880
|
+
function getSeason(month) {
|
|
3881
|
+
if (month >= 2 && month <= 4) return "Spring";
|
|
3882
|
+
if (month >= 5 && month <= 7) return "Summer";
|
|
3883
|
+
if (month >= 8 && month <= 10) return "Fall";
|
|
3884
|
+
return "Winter";
|
|
3885
|
+
}
|
|
3886
|
+
function isRecord2(value) {
|
|
3887
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3888
|
+
}
|
|
3889
|
+
function buildEnvironmentSnapshot(now, options) {
|
|
3890
|
+
const { language, timeZone } = options;
|
|
3891
|
+
const currentDateTime = now.toLocaleString("en-CA", {
|
|
3892
|
+
timeZone,
|
|
3893
|
+
year: "numeric",
|
|
3894
|
+
month: "2-digit",
|
|
3895
|
+
day: "2-digit",
|
|
3896
|
+
hour: "2-digit",
|
|
3897
|
+
minute: "2-digit",
|
|
3898
|
+
second: "2-digit",
|
|
3899
|
+
hour12: false
|
|
3900
|
+
});
|
|
3901
|
+
const dayOfWeek = now.toLocaleString("default", {
|
|
3902
|
+
weekday: "long",
|
|
3903
|
+
timeZone
|
|
3904
|
+
});
|
|
3905
|
+
const month = now.toLocaleString("default", {
|
|
3906
|
+
month: "long",
|
|
3907
|
+
timeZone
|
|
3908
|
+
});
|
|
3909
|
+
const year = parseInt(
|
|
3910
|
+
now.toLocaleString("en-CA", { year: "numeric", timeZone }),
|
|
3911
|
+
10
|
|
3912
|
+
);
|
|
3913
|
+
const monthIndex = parseInt(now.toLocaleString("en-CA", { month: "numeric", timeZone }), 10) - 1;
|
|
3914
|
+
return {
|
|
3915
|
+
timeZone,
|
|
3916
|
+
language,
|
|
3917
|
+
currentDateTime,
|
|
3918
|
+
dateKey: now.toLocaleDateString("en-CA", { timeZone }),
|
|
3919
|
+
dayOfWeek,
|
|
3920
|
+
month,
|
|
3921
|
+
year,
|
|
3922
|
+
season: getSeason(monthIndex),
|
|
3923
|
+
timestamp: now.getTime()
|
|
3924
|
+
};
|
|
3925
|
+
}
|
|
3926
|
+
function buildEnvironmentBlock(snapshot) {
|
|
3927
|
+
return `TimeZone is always in ${snapshot.timeZone}.
|
|
3928
|
+
|
|
3929
|
+
Current Date & Time: "${snapshot.currentDateTime}"
|
|
3930
|
+
Day of Week: ${snapshot.dayOfWeek}
|
|
3931
|
+
Month: ${snapshot.month}
|
|
3932
|
+
Year: ${snapshot.year}
|
|
3933
|
+
Timestamp: ${snapshot.timestamp}
|
|
3934
|
+
Language: ${snapshot.language}
|
|
3935
|
+
Season: ${snapshot.season}`;
|
|
3936
|
+
}
|
|
3937
|
+
function formatChange(previous, current) {
|
|
3938
|
+
const changes = [];
|
|
3939
|
+
if (previous.timeZone !== current.timeZone) {
|
|
3940
|
+
changes.push(`time zone: ${previous.timeZone} -> ${current.timeZone}`);
|
|
3941
|
+
}
|
|
3942
|
+
if (previous.language !== current.language) {
|
|
3943
|
+
changes.push(`language: ${previous.language} -> ${current.language}`);
|
|
3944
|
+
}
|
|
3945
|
+
if (previous.dateKey !== current.dateKey) {
|
|
3946
|
+
changes.push(`date: ${previous.dateKey} -> ${current.dateKey}`);
|
|
3947
|
+
}
|
|
3948
|
+
if (previous.dayOfWeek !== current.dayOfWeek) {
|
|
3949
|
+
changes.push(`day of week: ${previous.dayOfWeek} -> ${current.dayOfWeek}`);
|
|
3950
|
+
}
|
|
3951
|
+
if (previous.month !== current.month) {
|
|
3952
|
+
changes.push(`month: ${previous.month} -> ${current.month}`);
|
|
3953
|
+
}
|
|
3954
|
+
if (previous.year !== current.year) {
|
|
3955
|
+
changes.push(`year: ${previous.year} -> ${current.year}`);
|
|
3956
|
+
}
|
|
3957
|
+
if (previous.season !== current.season) {
|
|
3958
|
+
changes.push(`season: ${previous.season} -> ${current.season}`);
|
|
3959
|
+
}
|
|
3960
|
+
return changes;
|
|
3961
|
+
}
|
|
3962
|
+
function buildChangeSummary(previous, current) {
|
|
3963
|
+
if (!previous) {
|
|
3964
|
+
return "";
|
|
3965
|
+
}
|
|
3966
|
+
const changes = formatChange(previous, current);
|
|
3967
|
+
if (changes.length === 0) {
|
|
3968
|
+
return "";
|
|
3969
|
+
}
|
|
3970
|
+
return `Changes since last environment snapshot:
|
|
3971
|
+
- ${changes.join("\n- ")}
|
|
3972
|
+
|
|
3973
|
+
`;
|
|
3974
|
+
}
|
|
3975
|
+
function parseEnvironmentSnapshot(value) {
|
|
3976
|
+
if (!isRecord2(value)) {
|
|
3977
|
+
return null;
|
|
3978
|
+
}
|
|
3979
|
+
if (typeof value.timeZone !== "string" || typeof value.language !== "string" || typeof value.currentDateTime !== "string" || typeof value.dateKey !== "string" || typeof value.dayOfWeek !== "string" || typeof value.month !== "string" || typeof value.year !== "number" || typeof value.season !== "string" || typeof value.timestamp !== "number") {
|
|
3980
|
+
return null;
|
|
3981
|
+
}
|
|
3982
|
+
return {
|
|
3983
|
+
timeZone: value.timeZone,
|
|
3984
|
+
language: value.language,
|
|
3985
|
+
currentDateTime: value.currentDateTime,
|
|
3986
|
+
dateKey: value.dateKey,
|
|
3987
|
+
dayOfWeek: value.dayOfWeek,
|
|
3988
|
+
month: value.month,
|
|
3989
|
+
year: value.year,
|
|
3990
|
+
season: value.season,
|
|
3991
|
+
timestamp: value.timestamp
|
|
3992
|
+
};
|
|
3993
|
+
}
|
|
3994
|
+
function getEnvironmentSnapshot(message2) {
|
|
3995
|
+
const metadata = isRecord2(message2?.metadata) ? message2.metadata : null;
|
|
3996
|
+
if (!metadata) {
|
|
3997
|
+
return null;
|
|
3998
|
+
}
|
|
3999
|
+
const stored = metadata[ENVIRONMENT_REMINDER_METADATA_KEY];
|
|
4000
|
+
if (!isRecord2(stored) || stored.version !== 1) {
|
|
4001
|
+
return null;
|
|
4002
|
+
}
|
|
4003
|
+
return parseEnvironmentSnapshot(stored.snapshot);
|
|
4004
|
+
}
|
|
4005
|
+
function environmentReminder(options) {
|
|
4006
|
+
const getNow = options?.getNow ?? (() => /* @__PURE__ */ new Date());
|
|
4007
|
+
const language = options?.language ?? "English (US)";
|
|
4008
|
+
const timeZone = options?.timeZone ?? "UTC";
|
|
4009
|
+
return reminder(
|
|
4010
|
+
(ctx) => {
|
|
4011
|
+
const snapshot = buildEnvironmentSnapshot(getNow(), {
|
|
4012
|
+
language,
|
|
4013
|
+
timeZone
|
|
4014
|
+
});
|
|
4015
|
+
const previousSnapshot = getEnvironmentSnapshot(ctx.lastMessage);
|
|
4016
|
+
const summary = buildChangeSummary(previousSnapshot, snapshot);
|
|
4017
|
+
return {
|
|
4018
|
+
text: `${summary}${buildEnvironmentBlock(snapshot)}`,
|
|
4019
|
+
metadata: {
|
|
4020
|
+
[ENVIRONMENT_REMINDER_METADATA_KEY]: {
|
|
4021
|
+
version: 1,
|
|
4022
|
+
snapshot
|
|
4023
|
+
}
|
|
4024
|
+
}
|
|
4025
|
+
};
|
|
4026
|
+
},
|
|
4027
|
+
{ when: everyNTurns(1) }
|
|
4028
|
+
);
|
|
4029
|
+
}
|
|
4030
|
+
|
|
3817
4031
|
// packages/context/src/lib/fragments/reasoning.ts
|
|
3818
4032
|
function reasoningFramework() {
|
|
3819
4033
|
return [
|
|
@@ -3938,6 +4152,68 @@ function selfCritique(checks = DEFAULT_SELF_CRITIQUE_CHECKS) {
|
|
|
3938
4152
|
});
|
|
3939
4153
|
}
|
|
3940
4154
|
|
|
4155
|
+
// packages/context/src/lib/fragments/socratic.ts
|
|
4156
|
+
function socraticPrompting() {
|
|
4157
|
+
return [
|
|
4158
|
+
role(
|
|
4159
|
+
"You are a deep, methodical thinker. Before producing any output, you reason through the problem by asking and answering foundational questions. You never treat a request as a simple task to complete \u2014 you first build understanding through inquiry, then apply that understanding to produce high-quality output."
|
|
4160
|
+
),
|
|
4161
|
+
fragment(
|
|
4162
|
+
"socratic_prompting",
|
|
4163
|
+
hint(
|
|
4164
|
+
"When given a task, do not jump straight to producing output. Instead, decompose the task into foundational questions that, once answered, will make the output significantly better. Answer those questions first, then synthesize your answers into the final output."
|
|
4165
|
+
),
|
|
4166
|
+
principle({
|
|
4167
|
+
title: "Question-first decomposition",
|
|
4168
|
+
description: 'Every task hides assumptions about what "good" looks like. Surface those assumptions by asking what makes the output effective before attempting to produce it.',
|
|
4169
|
+
policies: [
|
|
4170
|
+
'Ask "What makes X effective/compelling/useful?" before producing X.',
|
|
4171
|
+
"Identify the criteria, frameworks, or principles that govern quality for this type of output.",
|
|
4172
|
+
"Do not skip this step even when the task seems straightforward \u2014 obvious tasks often have non-obvious quality dimensions."
|
|
4173
|
+
]
|
|
4174
|
+
}),
|
|
4175
|
+
principle({
|
|
4176
|
+
title: "Multi-dimensional inquiry",
|
|
4177
|
+
description: "Explore the problem from multiple angles \u2014 emotional, logical, practical, audience-specific \u2014 through targeted questions.",
|
|
4178
|
+
policies: [
|
|
4179
|
+
"Ask about the audience: Who is this for? What do they care about?",
|
|
4180
|
+
"Ask about constraints: What must this include or avoid?",
|
|
4181
|
+
"Ask about effectiveness: What separates great output from mediocre output in this domain?",
|
|
4182
|
+
"Ask about structure: How should this be organized for maximum impact?"
|
|
4183
|
+
]
|
|
4184
|
+
}),
|
|
4185
|
+
principle({
|
|
4186
|
+
title: "Framework discovery before application",
|
|
4187
|
+
description: "Build or recall a relevant framework by reasoning through questions, then explicitly apply that framework to the specific task.",
|
|
4188
|
+
policies: [
|
|
4189
|
+
"First derive the framework: What principles govern this type of work?",
|
|
4190
|
+
'Then apply it: "Now, using these principles, produce the specific output."',
|
|
4191
|
+
"The framework should emerge from your reasoning, not from a template."
|
|
4192
|
+
]
|
|
4193
|
+
}),
|
|
4194
|
+
workflow({
|
|
4195
|
+
task: "Socratic reasoning process",
|
|
4196
|
+
steps: [
|
|
4197
|
+
"Identify the core task and desired output type.",
|
|
4198
|
+
"Formulate 2-5 foundational questions about what makes this output effective.",
|
|
4199
|
+
"Answer each question, drawing on relevant knowledge and frameworks.",
|
|
4200
|
+
"Synthesize answers into a coherent set of principles or criteria.",
|
|
4201
|
+
"Apply the discovered framework to produce the specific output.",
|
|
4202
|
+
"Verify the output satisfies the criteria you identified."
|
|
4203
|
+
]
|
|
4204
|
+
}),
|
|
4205
|
+
example({
|
|
4206
|
+
question: "How should I prompt for a value proposition for my AI analytics tool?",
|
|
4207
|
+
answer: "What makes a value proposition compelling to B2B buyers? What emotional and logical triggers should it hit? Now apply that framework to an AI analytics tool that helps teams make faster data-driven decisions."
|
|
4208
|
+
}),
|
|
4209
|
+
example({
|
|
4210
|
+
question: "How should I prompt for a 30-day LinkedIn content calendar for B2B SaaS?",
|
|
4211
|
+
answer: "What types of LinkedIn content generate the most engagement in B2B SaaS? What posting frequency avoids audience fatigue? How should topics build on each other? Now design a 30-day calendar using these principles."
|
|
4212
|
+
})
|
|
4213
|
+
)
|
|
4214
|
+
];
|
|
4215
|
+
}
|
|
4216
|
+
|
|
3941
4217
|
// packages/context/src/lib/guardrails/error-recovery.guardrail.ts
|
|
3942
4218
|
import chalk2 from "chalk";
|
|
3943
4219
|
var errorRecoveryGuardrail = {
|
|
@@ -4046,6 +4322,107 @@ function render(tag, ...fragments) {
|
|
|
4046
4322
|
return renderer.render([wrapped]);
|
|
4047
4323
|
}
|
|
4048
4324
|
|
|
4325
|
+
// packages/context/src/lib/sandbox/agent-os-sandbox.ts
|
|
4326
|
+
import "bash-tool";
|
|
4327
|
+
var textDecoder = new TextDecoder();
|
|
4328
|
+
var AgentOsSandboxError = class extends Error {
|
|
4329
|
+
constructor(message2) {
|
|
4330
|
+
super(message2);
|
|
4331
|
+
this.name = "AgentOsSandboxError";
|
|
4332
|
+
}
|
|
4333
|
+
};
|
|
4334
|
+
var AgentOsNotAvailableError = class extends AgentOsSandboxError {
|
|
4335
|
+
constructor(cause) {
|
|
4336
|
+
super(
|
|
4337
|
+
"@rivet-dev/agent-os-core is not installed. Install it with: npm install @rivet-dev/agent-os-core @rivet-dev/agent-os-common"
|
|
4338
|
+
);
|
|
4339
|
+
this.name = "AgentOsNotAvailableError";
|
|
4340
|
+
this.cause = cause;
|
|
4341
|
+
}
|
|
4342
|
+
};
|
|
4343
|
+
var AgentOsCreationError = class extends AgentOsSandboxError {
|
|
4344
|
+
constructor(message2, cause) {
|
|
4345
|
+
super(`Failed to create Agent OS instance: ${message2}`);
|
|
4346
|
+
this.name = "AgentOsCreationError";
|
|
4347
|
+
this.cause = cause;
|
|
4348
|
+
}
|
|
4349
|
+
};
|
|
4350
|
+
async function importAgentOs() {
|
|
4351
|
+
try {
|
|
4352
|
+
return await import("@rivet-dev/agent-os-core");
|
|
4353
|
+
} catch (error) {
|
|
4354
|
+
throw new AgentOsNotAvailableError(
|
|
4355
|
+
error instanceof Error ? error : void 0
|
|
4356
|
+
);
|
|
4357
|
+
}
|
|
4358
|
+
}
|
|
4359
|
+
async function createAgentOsSandbox(options = {}) {
|
|
4360
|
+
const { AgentOs } = await importAgentOs();
|
|
4361
|
+
let os;
|
|
4362
|
+
try {
|
|
4363
|
+
os = await AgentOs.create(options);
|
|
4364
|
+
} catch (error) {
|
|
4365
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
4366
|
+
throw new AgentOsCreationError(err.message, err);
|
|
4367
|
+
}
|
|
4368
|
+
return {
|
|
4369
|
+
async executeCommand(command) {
|
|
4370
|
+
try {
|
|
4371
|
+
const result = await os.exec(command);
|
|
4372
|
+
return {
|
|
4373
|
+
stdout: result.stdout,
|
|
4374
|
+
stderr: result.stderr,
|
|
4375
|
+
exitCode: result.exitCode
|
|
4376
|
+
};
|
|
4377
|
+
} catch (error) {
|
|
4378
|
+
const err = error;
|
|
4379
|
+
return {
|
|
4380
|
+
stdout: err.stdout || "",
|
|
4381
|
+
stderr: err.stderr || err.message || "",
|
|
4382
|
+
exitCode: err.exitCode ?? 1
|
|
4383
|
+
};
|
|
4384
|
+
}
|
|
4385
|
+
},
|
|
4386
|
+
async readFile(path3) {
|
|
4387
|
+
try {
|
|
4388
|
+
const bytes = await os.readFile(path3);
|
|
4389
|
+
return textDecoder.decode(bytes);
|
|
4390
|
+
} catch (error) {
|
|
4391
|
+
throw new Error(
|
|
4392
|
+
`Failed to read file "${path3}": ${error instanceof Error ? error.message : String(error)}`
|
|
4393
|
+
);
|
|
4394
|
+
}
|
|
4395
|
+
},
|
|
4396
|
+
async writeFiles(files) {
|
|
4397
|
+
const results = await os.writeFiles(
|
|
4398
|
+
files.map((f) => ({
|
|
4399
|
+
path: f.path,
|
|
4400
|
+
content: typeof f.content === "string" ? f.content : new Uint8Array(f.content)
|
|
4401
|
+
}))
|
|
4402
|
+
);
|
|
4403
|
+
const failures = results.filter((r) => !r.success);
|
|
4404
|
+
if (failures.length > 0) {
|
|
4405
|
+
const details = failures.map((f) => `${f.path}: ${f.error}`).join(", ");
|
|
4406
|
+
throw new Error(`Failed to write files: ${details}`);
|
|
4407
|
+
}
|
|
4408
|
+
},
|
|
4409
|
+
async dispose() {
|
|
4410
|
+
try {
|
|
4411
|
+
await os.dispose();
|
|
4412
|
+
} catch {
|
|
4413
|
+
}
|
|
4414
|
+
}
|
|
4415
|
+
};
|
|
4416
|
+
}
|
|
4417
|
+
async function useAgentOsSandbox(options, fn) {
|
|
4418
|
+
const sandbox = await createAgentOsSandbox(options);
|
|
4419
|
+
try {
|
|
4420
|
+
return await fn(sandbox);
|
|
4421
|
+
} finally {
|
|
4422
|
+
await sandbox.dispose();
|
|
4423
|
+
}
|
|
4424
|
+
}
|
|
4425
|
+
|
|
4049
4426
|
// packages/context/src/lib/sandbox/binary-bridges.ts
|
|
4050
4427
|
import { existsSync } from "fs";
|
|
4051
4428
|
import { defineCommand } from "just-bash";
|
|
@@ -4142,6 +4519,11 @@ function resolveRealCwd(ctx) {
|
|
|
4142
4519
|
return realCwd;
|
|
4143
4520
|
}
|
|
4144
4521
|
|
|
4522
|
+
// packages/context/src/lib/sandbox/container-tool.ts
|
|
4523
|
+
import {
|
|
4524
|
+
createBashTool
|
|
4525
|
+
} from "bash-tool";
|
|
4526
|
+
|
|
4145
4527
|
// packages/context/src/lib/sandbox/docker-sandbox.ts
|
|
4146
4528
|
import "bash-tool";
|
|
4147
4529
|
import spawn2 from "nano-spawn";
|
|
@@ -4234,10 +4616,10 @@ var ComposeStartError = class extends DockerSandboxError {
|
|
|
4234
4616
|
}
|
|
4235
4617
|
};
|
|
4236
4618
|
function isDebianBased(image) {
|
|
4619
|
+
const lower = image.toLowerCase();
|
|
4620
|
+
if (lower.includes("alpine")) return false;
|
|
4237
4621
|
const debianPatterns = ["debian", "ubuntu", "node", "python"];
|
|
4238
|
-
return debianPatterns.some(
|
|
4239
|
-
(pattern) => image.toLowerCase().includes(pattern)
|
|
4240
|
-
);
|
|
4622
|
+
return debianPatterns.some((pattern) => lower.includes(pattern));
|
|
4241
4623
|
}
|
|
4242
4624
|
function isDockerfileOptions(opts) {
|
|
4243
4625
|
return "dockerfile" in opts;
|
|
@@ -4249,9 +4631,18 @@ var DockerSandboxStrategy = class {
|
|
|
4249
4631
|
context;
|
|
4250
4632
|
mounts;
|
|
4251
4633
|
resources;
|
|
4252
|
-
|
|
4634
|
+
env;
|
|
4635
|
+
constructor(mounts = [], resources = {}, env = {}) {
|
|
4636
|
+
for (const key of Object.keys(env)) {
|
|
4637
|
+
if (key.length === 0 || key.includes("=")) {
|
|
4638
|
+
throw new DockerSandboxError(
|
|
4639
|
+
`Invalid environment variable key: "${key}"`
|
|
4640
|
+
);
|
|
4641
|
+
}
|
|
4642
|
+
}
|
|
4253
4643
|
this.mounts = mounts;
|
|
4254
4644
|
this.resources = resources;
|
|
4645
|
+
this.env = env;
|
|
4255
4646
|
}
|
|
4256
4647
|
/**
|
|
4257
4648
|
* Template method - defines the algorithm skeleton for creating a sandbox.
|
|
@@ -4308,6 +4699,9 @@ var DockerSandboxStrategy = class {
|
|
|
4308
4699
|
"/workspace"
|
|
4309
4700
|
// Set working directory
|
|
4310
4701
|
];
|
|
4702
|
+
for (const [key, value] of Object.entries(this.env)) {
|
|
4703
|
+
args.push("-e", `${key}=${value}`);
|
|
4704
|
+
}
|
|
4311
4705
|
for (const mount of this.mounts) {
|
|
4312
4706
|
const mode = mount.readOnly !== false ? "ro" : "rw";
|
|
4313
4707
|
args.push("-v", `${mount.hostPath}:${mount.containerPath}:${mode}`);
|
|
@@ -4411,8 +4805,8 @@ var RuntimeStrategy = class extends DockerSandboxStrategy {
|
|
|
4411
4805
|
image;
|
|
4412
4806
|
packages;
|
|
4413
4807
|
binaries;
|
|
4414
|
-
constructor(image = "alpine:latest", packages = [], binaries = [], mounts, resources) {
|
|
4415
|
-
super(mounts, resources);
|
|
4808
|
+
constructor(image = "alpine:latest", packages = [], binaries = [], mounts, resources, env) {
|
|
4809
|
+
super(mounts, resources, env);
|
|
4416
4810
|
this.image = image;
|
|
4417
4811
|
this.packages = packages;
|
|
4418
4812
|
this.binaries = binaries;
|
|
@@ -4581,8 +4975,8 @@ var DockerfileStrategy = class extends DockerSandboxStrategy {
|
|
|
4581
4975
|
imageTag;
|
|
4582
4976
|
dockerfile;
|
|
4583
4977
|
dockerContext;
|
|
4584
|
-
constructor(dockerfile, dockerContext = ".", mounts, resources) {
|
|
4585
|
-
super(mounts, resources);
|
|
4978
|
+
constructor(dockerfile, dockerContext = ".", mounts, resources, env) {
|
|
4979
|
+
super(mounts, resources, env);
|
|
4586
4980
|
this.dockerfile = dockerfile;
|
|
4587
4981
|
this.dockerContext = dockerContext;
|
|
4588
4982
|
this.imageTag = this.computeImageTag();
|
|
@@ -4755,7 +5149,8 @@ async function createDockerSandbox(options = {}) {
|
|
|
4755
5149
|
options.dockerfile,
|
|
4756
5150
|
options.context,
|
|
4757
5151
|
options.mounts,
|
|
4758
|
-
options.resources
|
|
5152
|
+
options.resources,
|
|
5153
|
+
options.env
|
|
4759
5154
|
);
|
|
4760
5155
|
} else {
|
|
4761
5156
|
strategy = new RuntimeStrategy(
|
|
@@ -4763,7 +5158,8 @@ async function createDockerSandbox(options = {}) {
|
|
|
4763
5158
|
options.packages,
|
|
4764
5159
|
options.binaries,
|
|
4765
5160
|
options.mounts,
|
|
4766
|
-
options.resources
|
|
5161
|
+
options.resources,
|
|
5162
|
+
options.env
|
|
4767
5163
|
);
|
|
4768
5164
|
}
|
|
4769
5165
|
return strategy.create();
|
|
@@ -4778,9 +5174,6 @@ async function useSandbox(options, fn) {
|
|
|
4778
5174
|
}
|
|
4779
5175
|
|
|
4780
5176
|
// packages/context/src/lib/sandbox/container-tool.ts
|
|
4781
|
-
import {
|
|
4782
|
-
createBashTool
|
|
4783
|
-
} from "bash-tool";
|
|
4784
5177
|
async function createContainerTool(options = {}) {
|
|
4785
5178
|
let sandboxOptions;
|
|
4786
5179
|
let bashOptions;
|
|
@@ -4789,12 +5182,12 @@ async function createContainerTool(options = {}) {
|
|
|
4789
5182
|
sandboxOptions = { compose, service, resources };
|
|
4790
5183
|
bashOptions = rest;
|
|
4791
5184
|
} else if (isDockerfileOptions(options)) {
|
|
4792
|
-
const { dockerfile, context, mounts, resources, ...rest } = options;
|
|
4793
|
-
sandboxOptions = { dockerfile, context, mounts, resources };
|
|
5185
|
+
const { dockerfile, context, mounts, resources, env, ...rest } = options;
|
|
5186
|
+
sandboxOptions = { dockerfile, context, mounts, resources, env };
|
|
4794
5187
|
bashOptions = rest;
|
|
4795
5188
|
} else {
|
|
4796
|
-
const { image, packages, binaries, mounts, resources, ...rest } = options;
|
|
4797
|
-
sandboxOptions = { image, packages, binaries, mounts, resources };
|
|
5189
|
+
const { image, packages, binaries, mounts, resources, env, ...rest } = options;
|
|
5190
|
+
sandboxOptions = { image, packages, binaries, mounts, resources, env };
|
|
4798
5191
|
bashOptions = rest;
|
|
4799
5192
|
}
|
|
4800
5193
|
const sandbox = await createDockerSandbox(sandboxOptions);
|
|
@@ -7335,6 +7728,9 @@ function visualizeGraph(data) {
|
|
|
7335
7728
|
return lines.join("\n");
|
|
7336
7729
|
}
|
|
7337
7730
|
export {
|
|
7731
|
+
AgentOsCreationError,
|
|
7732
|
+
AgentOsNotAvailableError,
|
|
7733
|
+
AgentOsSandboxError,
|
|
7338
7734
|
BM25SkillClassifier,
|
|
7339
7735
|
BinaryInstallError,
|
|
7340
7736
|
ComposeStartError,
|
|
@@ -7350,6 +7746,7 @@ export {
|
|
|
7350
7746
|
DockerSandboxStrategy,
|
|
7351
7747
|
DockerfileBuildError,
|
|
7352
7748
|
DockerfileStrategy,
|
|
7749
|
+
ENVIRONMENT_REMINDER_METADATA_KEY,
|
|
7353
7750
|
InMemoryContextStore,
|
|
7354
7751
|
LAZY_ID,
|
|
7355
7752
|
MarkdownRenderer,
|
|
@@ -7381,23 +7778,27 @@ export {
|
|
|
7381
7778
|
clarification,
|
|
7382
7779
|
correction,
|
|
7383
7780
|
createAdaptivePollingState,
|
|
7781
|
+
createAgentOsSandbox,
|
|
7384
7782
|
createBinaryBridges,
|
|
7385
7783
|
createContainerTool,
|
|
7386
7784
|
createDockerSandbox,
|
|
7387
7785
|
defaultTokenizer,
|
|
7388
7786
|
discoverSkillsInDirectory,
|
|
7389
7787
|
encodeSerializedValue,
|
|
7788
|
+
environmentReminder,
|
|
7390
7789
|
errorRecoveryGuardrail,
|
|
7391
7790
|
estimate,
|
|
7392
7791
|
everyNTurns,
|
|
7393
7792
|
example,
|
|
7394
7793
|
explain,
|
|
7794
|
+
extractPlainText,
|
|
7395
7795
|
fail,
|
|
7396
7796
|
firstN,
|
|
7397
7797
|
fragment,
|
|
7398
7798
|
fromFragment,
|
|
7399
7799
|
generateChatTitle,
|
|
7400
7800
|
getConditionalReminder,
|
|
7801
|
+
getEnvironmentSnapshot,
|
|
7401
7802
|
getFragmentData,
|
|
7402
7803
|
getModelsRegistry,
|
|
7403
7804
|
getReminderRanges,
|
|
@@ -7414,6 +7815,7 @@ export {
|
|
|
7414
7815
|
isMessageFragment,
|
|
7415
7816
|
lastAssistantMessage,
|
|
7416
7817
|
loadSkillMetadata,
|
|
7818
|
+
mergeMessageMetadata,
|
|
7417
7819
|
mergeReminderMetadata,
|
|
7418
7820
|
message,
|
|
7419
7821
|
nextAdaptivePollingDelay,
|
|
@@ -7434,12 +7836,14 @@ export {
|
|
|
7434
7836
|
reminder,
|
|
7435
7837
|
render,
|
|
7436
7838
|
resetAdaptivePolling,
|
|
7839
|
+
resolveReminder,
|
|
7437
7840
|
resolveReminderText,
|
|
7438
7841
|
role,
|
|
7439
7842
|
runGuardrailChain,
|
|
7440
7843
|
selfCritique,
|
|
7441
7844
|
skills,
|
|
7442
7845
|
skillsReminder,
|
|
7846
|
+
socraticPrompting,
|
|
7443
7847
|
soul,
|
|
7444
7848
|
staticChatTitle,
|
|
7445
7849
|
stop,
|
|
@@ -7450,6 +7854,7 @@ export {
|
|
|
7450
7854
|
term,
|
|
7451
7855
|
toFragment,
|
|
7452
7856
|
toMessageFragment,
|
|
7857
|
+
useAgentOsSandbox,
|
|
7453
7858
|
useSandbox,
|
|
7454
7859
|
user,
|
|
7455
7860
|
visualizeGraph,
|