open-agents-ai 0.187.382 → 0.187.385
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/index.js +301 -89
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10955,11 +10955,11 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
10955
10955
|
nodePaths.push(globalDir2);
|
|
10956
10956
|
} catch {
|
|
10957
10957
|
}
|
|
10958
|
-
const { openSync:
|
|
10958
|
+
const { openSync: openSync3, closeSync: closeSync3 } = await import("node:fs");
|
|
10959
10959
|
const daemonLogPath = join15(this.nexusDir, "daemon.log");
|
|
10960
10960
|
const daemonErrPath = join15(this.nexusDir, "daemon.err");
|
|
10961
|
-
const outFd =
|
|
10962
|
-
const errFd =
|
|
10961
|
+
const outFd = openSync3(daemonLogPath, "w");
|
|
10962
|
+
const errFd = openSync3(daemonErrPath, "w");
|
|
10963
10963
|
const child = spawn2("node", [daemonPath, this.nexusDir, agentName, agentType], {
|
|
10964
10964
|
detached: true,
|
|
10965
10965
|
stdio: ["ignore", outFd, errFd],
|
|
@@ -10968,11 +10968,11 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
10968
10968
|
});
|
|
10969
10969
|
child.unref();
|
|
10970
10970
|
try {
|
|
10971
|
-
|
|
10971
|
+
closeSync3(outFd);
|
|
10972
10972
|
} catch {
|
|
10973
10973
|
}
|
|
10974
10974
|
try {
|
|
10975
|
-
|
|
10975
|
+
closeSync3(errFd);
|
|
10976
10976
|
} catch {
|
|
10977
10977
|
}
|
|
10978
10978
|
const statusFile = join15(this.nexusDir, "status.json");
|
|
@@ -33929,11 +33929,11 @@ var init_storage = __esm({
|
|
|
33929
33929
|
*/
|
|
33930
33930
|
async put(cid, block, options2 = {}) {
|
|
33931
33931
|
options2?.signal?.throwIfAborted();
|
|
33932
|
-
const
|
|
33932
|
+
const releaseLock2 = await this.lock.readLock();
|
|
33933
33933
|
try {
|
|
33934
33934
|
return await this.child.put(cid, block, options2);
|
|
33935
33935
|
} finally {
|
|
33936
|
-
|
|
33936
|
+
releaseLock2();
|
|
33937
33937
|
}
|
|
33938
33938
|
}
|
|
33939
33939
|
/**
|
|
@@ -33941,11 +33941,11 @@ var init_storage = __esm({
|
|
|
33941
33941
|
*/
|
|
33942
33942
|
async *putMany(blocks, options2 = {}) {
|
|
33943
33943
|
options2?.signal?.throwIfAborted();
|
|
33944
|
-
const
|
|
33944
|
+
const releaseLock2 = await this.lock.readLock();
|
|
33945
33945
|
try {
|
|
33946
33946
|
yield* this.child.putMany(blocks, options2);
|
|
33947
33947
|
} finally {
|
|
33948
|
-
|
|
33948
|
+
releaseLock2();
|
|
33949
33949
|
}
|
|
33950
33950
|
}
|
|
33951
33951
|
/**
|
|
@@ -33953,11 +33953,11 @@ var init_storage = __esm({
|
|
|
33953
33953
|
*/
|
|
33954
33954
|
async *get(cid, options2 = {}) {
|
|
33955
33955
|
options2?.signal?.throwIfAborted();
|
|
33956
|
-
const
|
|
33956
|
+
const releaseLock2 = await this.lock.readLock();
|
|
33957
33957
|
try {
|
|
33958
33958
|
yield* this.child.get(cid, options2);
|
|
33959
33959
|
} finally {
|
|
33960
|
-
|
|
33960
|
+
releaseLock2();
|
|
33961
33961
|
}
|
|
33962
33962
|
}
|
|
33963
33963
|
/**
|
|
@@ -33965,11 +33965,11 @@ var init_storage = __esm({
|
|
|
33965
33965
|
*/
|
|
33966
33966
|
async *getMany(cids, options2 = {}) {
|
|
33967
33967
|
options2?.signal?.throwIfAborted();
|
|
33968
|
-
const
|
|
33968
|
+
const releaseLock2 = await this.lock.readLock();
|
|
33969
33969
|
try {
|
|
33970
33970
|
yield* this.child.getMany(cids, options2);
|
|
33971
33971
|
} finally {
|
|
33972
|
-
|
|
33972
|
+
releaseLock2();
|
|
33973
33973
|
}
|
|
33974
33974
|
}
|
|
33975
33975
|
/**
|
|
@@ -33977,14 +33977,14 @@ var init_storage = __esm({
|
|
|
33977
33977
|
*/
|
|
33978
33978
|
async delete(cid, options2 = {}) {
|
|
33979
33979
|
options2?.signal?.throwIfAborted();
|
|
33980
|
-
const
|
|
33980
|
+
const releaseLock2 = await this.lock.writeLock();
|
|
33981
33981
|
try {
|
|
33982
33982
|
if (await this.pins.isPinned(cid)) {
|
|
33983
33983
|
throw new BlockPinnedError("Block was pinned - please unpin and try again");
|
|
33984
33984
|
}
|
|
33985
33985
|
await this.child.delete(cid, options2);
|
|
33986
33986
|
} finally {
|
|
33987
|
-
|
|
33987
|
+
releaseLock2();
|
|
33988
33988
|
}
|
|
33989
33989
|
}
|
|
33990
33990
|
/**
|
|
@@ -33992,7 +33992,7 @@ var init_storage = __esm({
|
|
|
33992
33992
|
*/
|
|
33993
33993
|
async *deleteMany(cids, options2 = {}) {
|
|
33994
33994
|
options2?.signal?.throwIfAborted();
|
|
33995
|
-
const
|
|
33995
|
+
const releaseLock2 = await this.lock.writeLock();
|
|
33996
33996
|
try {
|
|
33997
33997
|
const storage = this;
|
|
33998
33998
|
yield* this.child.deleteMany((async function* () {
|
|
@@ -34004,25 +34004,25 @@ var init_storage = __esm({
|
|
|
34004
34004
|
}
|
|
34005
34005
|
})(), options2);
|
|
34006
34006
|
} finally {
|
|
34007
|
-
|
|
34007
|
+
releaseLock2();
|
|
34008
34008
|
}
|
|
34009
34009
|
}
|
|
34010
34010
|
async has(cid, options2 = {}) {
|
|
34011
34011
|
options2?.signal?.throwIfAborted();
|
|
34012
|
-
const
|
|
34012
|
+
const releaseLock2 = await this.lock.readLock();
|
|
34013
34013
|
try {
|
|
34014
34014
|
return await this.child.has(cid, options2);
|
|
34015
34015
|
} finally {
|
|
34016
|
-
|
|
34016
|
+
releaseLock2();
|
|
34017
34017
|
}
|
|
34018
34018
|
}
|
|
34019
34019
|
async *getAll(options2 = {}) {
|
|
34020
34020
|
options2?.signal?.throwIfAborted();
|
|
34021
|
-
const
|
|
34021
|
+
const releaseLock2 = await this.lock.readLock();
|
|
34022
34022
|
try {
|
|
34023
34023
|
yield* this.child.getAll(options2);
|
|
34024
34024
|
} finally {
|
|
34025
|
-
|
|
34025
|
+
releaseLock2();
|
|
34026
34026
|
}
|
|
34027
34027
|
}
|
|
34028
34028
|
createSession(root, options2) {
|
|
@@ -36869,7 +36869,7 @@ var init_src38 = __esm({
|
|
|
36869
36869
|
this.events.dispatchEvent(new CustomEvent("stop", { detail: this }));
|
|
36870
36870
|
}
|
|
36871
36871
|
async gc(options2 = {}) {
|
|
36872
|
-
const
|
|
36872
|
+
const releaseLock2 = await this.blockstore.lock.writeLock();
|
|
36873
36873
|
try {
|
|
36874
36874
|
const helia = this;
|
|
36875
36875
|
const blockstore = this.blockstore.unwrap();
|
|
@@ -36889,7 +36889,7 @@ var init_src38 = __esm({
|
|
|
36889
36889
|
}
|
|
36890
36890
|
})()));
|
|
36891
36891
|
} finally {
|
|
36892
|
-
|
|
36892
|
+
releaseLock2();
|
|
36893
36893
|
}
|
|
36894
36894
|
this.log("gc finished");
|
|
36895
36895
|
}
|
|
@@ -529603,7 +529603,7 @@ __export(oa_directory_exports, {
|
|
|
529603
529603
|
writeIndexData: () => writeIndexData,
|
|
529604
529604
|
writeIndexMeta: () => writeIndexMeta
|
|
529605
529605
|
});
|
|
529606
|
-
import { existsSync as existsSync57, mkdirSync as mkdirSync32, readFileSync as readFileSync44, writeFileSync as writeFileSync29, readdirSync as readdirSync14, statSync as statSync17, unlinkSync as unlinkSync14 } from "node:fs";
|
|
529606
|
+
import { existsSync as existsSync57, mkdirSync as mkdirSync32, readFileSync as readFileSync44, writeFileSync as writeFileSync29, readdirSync as readdirSync14, statSync as statSync17, unlinkSync as unlinkSync14, openSync as openSync2, closeSync as closeSync2 } from "node:fs";
|
|
529607
529607
|
import { join as join75, relative as relative6, basename as basename13 } from "node:path";
|
|
529608
529608
|
import { homedir as homedir25 } from "node:os";
|
|
529609
529609
|
function initOaDirectory(repoRoot) {
|
|
@@ -529838,33 +529838,204 @@ function loadPendingTask(repoRoot) {
|
|
|
529838
529838
|
return null;
|
|
529839
529839
|
}
|
|
529840
529840
|
}
|
|
529841
|
+
function acquireLock(lockPath) {
|
|
529842
|
+
const startTime = Date.now();
|
|
529843
|
+
const pid = process.pid;
|
|
529844
|
+
for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
|
|
529845
|
+
try {
|
|
529846
|
+
const fd = openSync2(lockPath, "wx");
|
|
529847
|
+
const lockData = JSON.stringify({ pid, acquiredAt: Date.now() });
|
|
529848
|
+
writeFileSync29(fd, lockData);
|
|
529849
|
+
closeSync2(fd);
|
|
529850
|
+
return true;
|
|
529851
|
+
} catch (err) {
|
|
529852
|
+
if (existsSync57(lockPath)) {
|
|
529853
|
+
try {
|
|
529854
|
+
const lockContent = readFileSync44(lockPath, "utf-8");
|
|
529855
|
+
const lock = JSON.parse(lockContent);
|
|
529856
|
+
const lockAge = Date.now() - lock.acquiredAt;
|
|
529857
|
+
if (lockAge > LOCK_TIMEOUT_MS) {
|
|
529858
|
+
try {
|
|
529859
|
+
unlinkSync14(lockPath);
|
|
529860
|
+
} catch {
|
|
529861
|
+
}
|
|
529862
|
+
}
|
|
529863
|
+
} catch {
|
|
529864
|
+
try {
|
|
529865
|
+
unlinkSync14(lockPath);
|
|
529866
|
+
} catch {
|
|
529867
|
+
}
|
|
529868
|
+
}
|
|
529869
|
+
}
|
|
529870
|
+
if (Date.now() - startTime < LOCK_TIMEOUT_MS) {
|
|
529871
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, LOCK_RETRY_MS);
|
|
529872
|
+
}
|
|
529873
|
+
}
|
|
529874
|
+
}
|
|
529875
|
+
return false;
|
|
529876
|
+
}
|
|
529877
|
+
function releaseLock(lockPath) {
|
|
529878
|
+
try {
|
|
529879
|
+
if (existsSync57(lockPath)) {
|
|
529880
|
+
const lockContent = readFileSync44(lockPath, "utf-8");
|
|
529881
|
+
const lock = JSON.parse(lockContent);
|
|
529882
|
+
if (lock.pid === process.pid) {
|
|
529883
|
+
unlinkSync14(lockPath);
|
|
529884
|
+
}
|
|
529885
|
+
}
|
|
529886
|
+
} catch {
|
|
529887
|
+
}
|
|
529888
|
+
}
|
|
529889
|
+
function normalizeSessionText(raw, maxLen = 500) {
|
|
529890
|
+
if (!raw) return "";
|
|
529891
|
+
return String(raw).replace(/\s+/g, " ").trim().slice(0, maxLen);
|
|
529892
|
+
}
|
|
529893
|
+
function normalizeList(items, maxItems) {
|
|
529894
|
+
if (!items || items.length === 0) return void 0;
|
|
529895
|
+
const seen = /* @__PURE__ */ new Set();
|
|
529896
|
+
const out = [];
|
|
529897
|
+
for (const item of items) {
|
|
529898
|
+
const clean3 = normalizeSessionText(item, 300);
|
|
529899
|
+
if (!clean3 || seen.has(clean3)) continue;
|
|
529900
|
+
seen.add(clean3);
|
|
529901
|
+
out.push(clean3);
|
|
529902
|
+
if (out.length >= maxItems) break;
|
|
529903
|
+
}
|
|
529904
|
+
return out.length > 0 ? out : void 0;
|
|
529905
|
+
}
|
|
529906
|
+
function normalizeSessionContextEntry(entry) {
|
|
529907
|
+
const normalized = {
|
|
529908
|
+
...entry,
|
|
529909
|
+
savedAt: entry.savedAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
529910
|
+
task: cleanPromptForDiary(entry.task).slice(0, 500),
|
|
529911
|
+
summary: normalizeSessionText(entry.summary, 500),
|
|
529912
|
+
filesModified: normalizeList(entry.filesModified, 30) ?? [],
|
|
529913
|
+
toolCalls: Math.max(0, entry.toolCalls ?? 0),
|
|
529914
|
+
completed: Boolean(entry.completed),
|
|
529915
|
+
model: normalizeSessionText(entry.model, 160)
|
|
529916
|
+
};
|
|
529917
|
+
const toolsUsed = normalizeList(entry.toolsUsed, 12);
|
|
529918
|
+
if (toolsUsed) normalized.toolsUsed = toolsUsed;
|
|
529919
|
+
const provenance = normalizeSessionText(entry.provenance, 300);
|
|
529920
|
+
if (provenance) normalized.provenance = provenance;
|
|
529921
|
+
const assistantResponse = normalizeSessionText(entry.assistantResponse, 1200);
|
|
529922
|
+
if (assistantResponse) normalized.assistantResponse = assistantResponse;
|
|
529923
|
+
if (entry.source) normalized.source = entry.source;
|
|
529924
|
+
return normalized;
|
|
529925
|
+
}
|
|
529926
|
+
function sameStringArray(a2, b) {
|
|
529927
|
+
const left = a2 ?? [];
|
|
529928
|
+
const right = b ?? [];
|
|
529929
|
+
if (left.length !== right.length) return false;
|
|
529930
|
+
for (let i2 = 0; i2 < left.length; i2++) {
|
|
529931
|
+
if (left[i2] !== right[i2]) return false;
|
|
529932
|
+
}
|
|
529933
|
+
return true;
|
|
529934
|
+
}
|
|
529935
|
+
function lastMatchingIndex(items, predicate) {
|
|
529936
|
+
for (let i2 = items.length - 1; i2 >= 0; i2--) {
|
|
529937
|
+
if (predicate(items[i2])) return i2;
|
|
529938
|
+
}
|
|
529939
|
+
return -1;
|
|
529940
|
+
}
|
|
529941
|
+
function sameTask(a2, b) {
|
|
529942
|
+
return cleanPromptForDiary(a2.task) === cleanPromptForDiary(b.task);
|
|
529943
|
+
}
|
|
529944
|
+
function parseIsoMs(value2) {
|
|
529945
|
+
if (!value2) return null;
|
|
529946
|
+
const ms = Date.parse(value2);
|
|
529947
|
+
return Number.isFinite(ms) ? ms : null;
|
|
529948
|
+
}
|
|
529949
|
+
function isWithinReplaceWindow(a2, b) {
|
|
529950
|
+
const left = parseIsoMs(a2.savedAt);
|
|
529951
|
+
const right = parseIsoMs(b.savedAt);
|
|
529952
|
+
if (left == null || right == null) return true;
|
|
529953
|
+
return Math.abs(right - left) <= SAME_TASK_REPLACE_WINDOW_MS;
|
|
529954
|
+
}
|
|
529955
|
+
function isExactSessionDuplicate(a2, b) {
|
|
529956
|
+
return sameTask(a2, b) && a2.summary === b.summary && (a2.assistantResponse ?? "") === (b.assistantResponse ?? "") && sameStringArray(a2.filesModified, b.filesModified) && sameStringArray(a2.toolsUsed, b.toolsUsed) && (a2.provenance ?? "") === (b.provenance ?? "") && a2.toolCalls === b.toolCalls && a2.completed === b.completed && a2.model === b.model;
|
|
529957
|
+
}
|
|
529958
|
+
function mergeSessionContextEntry(previous, incoming) {
|
|
529959
|
+
return {
|
|
529960
|
+
...previous,
|
|
529961
|
+
...incoming,
|
|
529962
|
+
savedAt: incoming.savedAt || previous.savedAt,
|
|
529963
|
+
task: incoming.task || previous.task,
|
|
529964
|
+
summary: incoming.summary || previous.summary,
|
|
529965
|
+
assistantResponse: incoming.assistantResponse || previous.assistantResponse || incoming.summary || previous.summary,
|
|
529966
|
+
filesModified: incoming.filesModified.length > 0 ? incoming.filesModified : previous.filesModified,
|
|
529967
|
+
toolCalls: Math.max(previous.toolCalls ?? 0, incoming.toolCalls ?? 0),
|
|
529968
|
+
toolsUsed: incoming.toolsUsed && incoming.toolsUsed.length > 0 ? incoming.toolsUsed : previous.toolsUsed,
|
|
529969
|
+
provenance: incoming.provenance || previous.provenance,
|
|
529970
|
+
completed: previous.completed || incoming.completed,
|
|
529971
|
+
model: incoming.model || previous.model,
|
|
529972
|
+
source: incoming.source || previous.source
|
|
529973
|
+
};
|
|
529974
|
+
}
|
|
529841
529975
|
function saveSessionContext(repoRoot, entry) {
|
|
529842
529976
|
const contextDir = join75(repoRoot, OA_DIR, "context");
|
|
529843
529977
|
mkdirSync32(contextDir, { recursive: true });
|
|
529844
529978
|
const filePath = join75(contextDir, CONTEXT_SAVE_FILE);
|
|
529845
|
-
|
|
529979
|
+
const lockPath = join75(contextDir, CONTEXT_SAVE_FILE + ".lock");
|
|
529980
|
+
const locked = acquireLock(lockPath);
|
|
529981
|
+
if (!locked) {
|
|
529982
|
+
console.warn("[saveSessionContext] Could not acquire lock, proceeding without mutex");
|
|
529983
|
+
}
|
|
529846
529984
|
try {
|
|
529847
|
-
|
|
529848
|
-
|
|
529849
|
-
|
|
529985
|
+
let ctx3;
|
|
529986
|
+
try {
|
|
529987
|
+
if (existsSync57(filePath)) {
|
|
529988
|
+
ctx3 = JSON.parse(readFileSync44(filePath, "utf-8"));
|
|
529989
|
+
} else {
|
|
529990
|
+
ctx3 = { entries: [], maxEntries: MAX_CONTEXT_ENTRIES, updatedAt: "" };
|
|
529991
|
+
}
|
|
529992
|
+
} catch {
|
|
529850
529993
|
ctx3 = { entries: [], maxEntries: MAX_CONTEXT_ENTRIES, updatedAt: "" };
|
|
529851
529994
|
}
|
|
529852
|
-
|
|
529853
|
-
|
|
529854
|
-
|
|
529855
|
-
|
|
529856
|
-
if (ctx3.entries.length > ctx3.maxEntries) {
|
|
529857
|
-
ctx3.entries = ctx3.entries.slice(-ctx3.maxEntries);
|
|
529858
|
-
}
|
|
529859
|
-
ctx3.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
529860
|
-
writeFileSync29(filePath, JSON.stringify(ctx3, null, 2) + "\n", "utf-8");
|
|
529861
|
-
try {
|
|
529862
|
-
writeFileSync29(
|
|
529863
|
-
join75(contextDir, "session-diary.md"),
|
|
529864
|
-
renderSessionDiary(ctx3.entries.slice(-10)),
|
|
529865
|
-
"utf-8"
|
|
529995
|
+
const normalizedEntry = normalizeSessionContextEntry(entry);
|
|
529996
|
+
const exactIndex = lastMatchingIndex(
|
|
529997
|
+
ctx3.entries,
|
|
529998
|
+
(existing) => isExactSessionDuplicate(normalizeSessionContextEntry(existing), normalizedEntry)
|
|
529866
529999
|
);
|
|
529867
|
-
|
|
530000
|
+
if (exactIndex >= 0) {
|
|
530001
|
+
ctx3.entries[exactIndex] = mergeSessionContextEntry(ctx3.entries[exactIndex], normalizedEntry);
|
|
530002
|
+
} else {
|
|
530003
|
+
const relatedIndex = lastMatchingIndex(ctx3.entries, (existing) => {
|
|
530004
|
+
const normalizedExisting = normalizeSessionContextEntry(existing);
|
|
530005
|
+
return sameTask(normalizedExisting, normalizedEntry) && isWithinReplaceWindow(normalizedExisting, normalizedEntry);
|
|
530006
|
+
});
|
|
530007
|
+
if (relatedIndex >= 0) {
|
|
530008
|
+
const previous = normalizeSessionContextEntry(ctx3.entries[relatedIndex]);
|
|
530009
|
+
const shouldDropPartialResave = previous.completed && !normalizedEntry.completed;
|
|
530010
|
+
const shouldReplaceExisting = !previous.completed || normalizedEntry.source === "manual" || previous.completed && normalizedEntry.completed;
|
|
530011
|
+
if (!shouldDropPartialResave) {
|
|
530012
|
+
if (shouldReplaceExisting) {
|
|
530013
|
+
ctx3.entries[relatedIndex] = mergeSessionContextEntry(ctx3.entries[relatedIndex], normalizedEntry);
|
|
530014
|
+
} else {
|
|
530015
|
+
ctx3.entries.push(normalizedEntry);
|
|
530016
|
+
}
|
|
530017
|
+
}
|
|
530018
|
+
} else {
|
|
530019
|
+
ctx3.entries.push(normalizedEntry);
|
|
530020
|
+
}
|
|
530021
|
+
}
|
|
530022
|
+
if (ctx3.entries.length > ctx3.maxEntries) {
|
|
530023
|
+
ctx3.entries = ctx3.entries.slice(-ctx3.maxEntries);
|
|
530024
|
+
}
|
|
530025
|
+
ctx3.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
530026
|
+
writeFileSync29(filePath, JSON.stringify(ctx3, null, 2) + "\n", "utf-8");
|
|
530027
|
+
try {
|
|
530028
|
+
writeFileSync29(
|
|
530029
|
+
join75(contextDir, "session-diary.md"),
|
|
530030
|
+
renderSessionDiary(ctx3.entries.slice(-10)),
|
|
530031
|
+
"utf-8"
|
|
530032
|
+
);
|
|
530033
|
+
} catch {
|
|
530034
|
+
}
|
|
530035
|
+
} finally {
|
|
530036
|
+
if (locked) {
|
|
530037
|
+
releaseLock(lockPath);
|
|
530038
|
+
}
|
|
529868
530039
|
}
|
|
529869
530040
|
}
|
|
529870
530041
|
function cleanPromptForDiary(raw) {
|
|
@@ -529912,6 +530083,9 @@ function renderSessionDiary(entries) {
|
|
|
529912
530083
|
if (e2.provenance) {
|
|
529913
530084
|
lines.push(`- **Provenance:** ${e2.provenance}`);
|
|
529914
530085
|
}
|
|
530086
|
+
if (e2.assistantResponse) {
|
|
530087
|
+
lines.push(`- **Assistant:** ${e2.assistantResponse.replace(/\s+/g, " ").trim().slice(0, 280)}`);
|
|
530088
|
+
}
|
|
529915
530089
|
if (e2.summary) {
|
|
529916
530090
|
const summary = e2.summary.replace(/\s+/g, " ").trim().slice(0, 280);
|
|
529917
530091
|
lines.push(`- **Summary:** ${summary}`);
|
|
@@ -529935,22 +530109,35 @@ function buildContextRestorePrompt(repoRoot) {
|
|
|
529935
530109
|
const ctx3 = loadSessionContext(repoRoot);
|
|
529936
530110
|
if (!ctx3 || ctx3.entries.length === 0) return null;
|
|
529937
530111
|
const recent = ctx3.entries.slice(-5);
|
|
529938
|
-
const
|
|
530112
|
+
const chronology = recent.map((e2) => {
|
|
529939
530113
|
const status = e2.completed ? "done" : "partial";
|
|
529940
|
-
const summary = e2.
|
|
530114
|
+
const summary = normalizeSessionText(e2.assistantResponse || e2.summary || e2.task, 140);
|
|
529941
530115
|
const tools = e2.toolsUsed && e2.toolsUsed.length > 0 ? ` | tools: ${e2.toolsUsed.slice(0, 4).join(", ")}` : "";
|
|
529942
530116
|
const files = e2.filesModified && e2.filesModified.length > 0 ? ` | files: ${e2.filesModified.slice(0, 3).join(", ")}` : "";
|
|
529943
530117
|
return `[${status}] ${summary}${tools}${files}`;
|
|
529944
530118
|
});
|
|
529945
530119
|
const last2 = ctx3.entries[ctx3.entries.length - 1];
|
|
530120
|
+
const lastCompleted = [...ctx3.entries].reverse().find((entry) => entry.completed);
|
|
530121
|
+
const latestCompleted = lastCompleted ? `Latest completed task: ${normalizeSessionText(lastCompleted.assistantResponse || lastCompleted.summary || lastCompleted.task, 180)}` : "";
|
|
530122
|
+
const recentDialogue = recent.slice(-3).map((entry) => {
|
|
530123
|
+
const assistant = normalizeSessionText(entry.assistantResponse || entry.summary, 320) || "(no assistant reply captured)";
|
|
530124
|
+
const user = cleanPromptForDiary(entry.task).slice(0, 220);
|
|
530125
|
+
return `User: ${user}
|
|
530126
|
+
Assistant: ${assistant}`;
|
|
530127
|
+
}).join("\n\n");
|
|
529946
530128
|
const prov = last2.provenance ? `
|
|
529947
530129
|
Provenance: ${last2.provenance} (file_read to expand)` : "";
|
|
529948
530130
|
const kg = `
|
|
529949
530131
|
KG summary: .oa/context/kg-summary-latest.md (file_read to expand)`;
|
|
529950
530132
|
return `<session-recap>
|
|
529951
|
-
|
|
529952
|
-
${
|
|
529953
|
-
|
|
530133
|
+
Project chronology (older to newer):
|
|
530134
|
+
${chronology.join("\n")}
|
|
530135
|
+
` + (latestCompleted ? `
|
|
530136
|
+
${latestCompleted}
|
|
530137
|
+
` : "\n") + `
|
|
530138
|
+
Most recent exchanges (older to newer):
|
|
530139
|
+
${recentDialogue}
|
|
530140
|
+
Continue from the latest exchange and do not repeat completed work.${prov}${kg}
|
|
529954
530141
|
</session-recap>`;
|
|
529955
530142
|
}
|
|
529956
530143
|
function getLastTaskSummary(repoRoot) {
|
|
@@ -530236,7 +530423,7 @@ function deleteUsageRecord(kind, value2, repoRoot) {
|
|
|
530236
530423
|
remove(join75(repoRoot, OA_DIR, USAGE_HISTORY_FILE));
|
|
530237
530424
|
}
|
|
530238
530425
|
}
|
|
530239
|
-
var OA_DIR, SUBDIRS, CONTEXT_FILES, PENDING_TASK_FILE, CONTEXT_SAVE_FILE, MAX_CONTEXT_ENTRIES, SESSIONS_DIR, SESSIONS_INDEX, SKIP_DIRS2, HOME_SKIP_DIRS, USAGE_HISTORY_FILE, MAX_HISTORY_RECORDS;
|
|
530426
|
+
var OA_DIR, SUBDIRS, CONTEXT_FILES, PENDING_TASK_FILE, CONTEXT_SAVE_FILE, MAX_CONTEXT_ENTRIES, SAME_TASK_REPLACE_WINDOW_MS, LOCK_TIMEOUT_MS, LOCK_RETRY_MS, LOCK_RETRY_MAX, SESSIONS_DIR, SESSIONS_INDEX, SKIP_DIRS2, HOME_SKIP_DIRS, USAGE_HISTORY_FILE, MAX_HISTORY_RECORDS;
|
|
530240
530427
|
var init_oa_directory = __esm({
|
|
530241
530428
|
"packages/cli/src/tui/oa-directory.ts"() {
|
|
530242
530429
|
"use strict";
|
|
@@ -530255,6 +530442,10 @@ var init_oa_directory = __esm({
|
|
|
530255
530442
|
PENDING_TASK_FILE = "pending-task.json";
|
|
530256
530443
|
CONTEXT_SAVE_FILE = "session-context.json";
|
|
530257
530444
|
MAX_CONTEXT_ENTRIES = 20;
|
|
530445
|
+
SAME_TASK_REPLACE_WINDOW_MS = 12 * 60 * 60 * 1e3;
|
|
530446
|
+
LOCK_TIMEOUT_MS = 5e3;
|
|
530447
|
+
LOCK_RETRY_MS = 50;
|
|
530448
|
+
LOCK_RETRY_MAX = 100;
|
|
530258
530449
|
SESSIONS_DIR = "sessions";
|
|
530259
530450
|
SESSIONS_INDEX = "sessions-index.json";
|
|
530260
530451
|
SKIP_DIRS2 = /* @__PURE__ */ new Set([
|
|
@@ -532003,6 +532194,9 @@ var init_status_bar = __esm({
|
|
|
532003
532194
|
// Since we're in alternate screen buffer, there's no native scrollback.
|
|
532004
532195
|
// NOTE: _contentLines is now a reference to the ACTIVE view's buffer.
|
|
532005
532196
|
_contentLines = [];
|
|
532197
|
+
/** Last buffered visible-line fingerprint — suppresses accidental double inserts */
|
|
532198
|
+
_lastBufferedFingerprint = "";
|
|
532199
|
+
_lastBufferedAt = 0;
|
|
532006
532200
|
_contentScrollOffset = 0;
|
|
532007
532201
|
// 0 = live (bottom), >0 = scrolled back
|
|
532008
532202
|
_contentMaxLines = 1e4;
|
|
@@ -532924,6 +533118,8 @@ var init_status_bar = __esm({
|
|
|
532924
533118
|
this._contentLines.splice(0, this._contentLines.length);
|
|
532925
533119
|
this._contentScrollOffset = 0;
|
|
532926
533120
|
this._inProgressLine = "";
|
|
533121
|
+
this._lastBufferedFingerprint = "";
|
|
533122
|
+
this._lastBufferedAt = 0;
|
|
532927
533123
|
this._autoScroll = true;
|
|
532928
533124
|
this.fillContentArea();
|
|
532929
533125
|
this.renderFooterAndPositionInput();
|
|
@@ -533615,9 +533811,10 @@ var init_status_bar = __esm({
|
|
|
533615
533811
|
self2._inProgressLine = combined.slice(lastNl + 1);
|
|
533616
533812
|
const completeLines = completed.split("\n");
|
|
533617
533813
|
for (const line of completeLines) {
|
|
533618
|
-
const
|
|
533619
|
-
|
|
533620
|
-
|
|
533814
|
+
const sanitized = self2.sanitizeBufferedContentLine(line);
|
|
533815
|
+
const visible = stripAnsi(sanitized);
|
|
533816
|
+
if (sanitized.length === 0 || visible.length > 0) {
|
|
533817
|
+
self2.bufferContentLine(sanitized);
|
|
533621
533818
|
}
|
|
533622
533819
|
}
|
|
533623
533820
|
}
|
|
@@ -533653,8 +533850,9 @@ ${CONTENT_BG_SEQ}`);
|
|
|
533653
533850
|
this.writeDepth = Math.max(0, this.writeDepth - 1);
|
|
533654
533851
|
if (this.writeDepth === 0) {
|
|
533655
533852
|
if (this._inProgressLine.length > 0) {
|
|
533656
|
-
const
|
|
533657
|
-
|
|
533853
|
+
const sanitized = this.sanitizeBufferedContentLine(this._inProgressLine);
|
|
533854
|
+
const visible = stripAnsi(sanitized);
|
|
533855
|
+
if (visible.length > 0) this.bufferContentLine(sanitized);
|
|
533658
533856
|
this._inProgressLine = "";
|
|
533659
533857
|
}
|
|
533660
533858
|
this._bufferContent = false;
|
|
@@ -533707,7 +533905,15 @@ ${CONTENT_BG_SEQ}`);
|
|
|
533707
533905
|
this.renderFooterAndPositionInput();
|
|
533708
533906
|
}
|
|
533709
533907
|
bufferContentLine(line) {
|
|
533710
|
-
this.
|
|
533908
|
+
const sanitized = this.sanitizeBufferedContentLine(line);
|
|
533909
|
+
const fingerprint = stripAnsi(sanitized).trim();
|
|
533910
|
+
const now = Date.now();
|
|
533911
|
+
if (fingerprint && fingerprint === this._lastBufferedFingerprint && now - this._lastBufferedAt < 50) {
|
|
533912
|
+
return;
|
|
533913
|
+
}
|
|
533914
|
+
this._lastBufferedFingerprint = fingerprint;
|
|
533915
|
+
this._lastBufferedAt = now;
|
|
533916
|
+
this._contentLines.push(sanitized);
|
|
533711
533917
|
if (this._contentLines.length > this._contentMaxLines) {
|
|
533712
533918
|
this._contentLines.splice(0, this._contentLines.length - this._contentMaxLines);
|
|
533713
533919
|
if (this._contentScrollOffset > 0) {
|
|
@@ -533719,6 +533925,10 @@ ${CONTENT_BG_SEQ}`);
|
|
|
533719
533925
|
}
|
|
533720
533926
|
if (this._autoScroll && !this._mouseSelecting) this._contentScrollOffset = 0;
|
|
533721
533927
|
}
|
|
533928
|
+
/** Keep SGR styling, drop replay-unsafe terminal control sequences from scrollback storage. */
|
|
533929
|
+
sanitizeBufferedContentLine(line) {
|
|
533930
|
+
return line.replace(/\r/g, "").replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, (seq) => seq.endsWith("m") ? seq : "");
|
|
533931
|
+
}
|
|
533722
533932
|
/**
|
|
533723
533933
|
* Remove the last N lines from the content scrollback buffer and repaint.
|
|
533724
533934
|
* Used by Esc-to-recall to erase the just-rendered user prompt.
|
|
@@ -556995,7 +557205,6 @@ function loadMemoryContext(repoRoot) {
|
|
|
556995
557205
|
}
|
|
556996
557206
|
function loadSessionHistory2(repoRoot) {
|
|
556997
557207
|
const sessions2 = loadRecentSessions(repoRoot, 5);
|
|
556998
|
-
if (sessions2.length === 0) return "";
|
|
556999
557208
|
const lines = ["Recent tasks in this project:"];
|
|
557000
557209
|
for (const s2 of sessions2) {
|
|
557001
557210
|
if (!s2.startedAt || !s2.task) continue;
|
|
@@ -557008,7 +557217,20 @@ function loadSessionHistory2(repoRoot) {
|
|
|
557008
557217
|
lines.push(` Summary: ${cleanSummary.slice(0, 120)}`);
|
|
557009
557218
|
}
|
|
557010
557219
|
}
|
|
557011
|
-
|
|
557220
|
+
const sessionCtx = loadSessionContext(repoRoot);
|
|
557221
|
+
const exchanges = sessionCtx?.entries.slice(-2) ?? [];
|
|
557222
|
+
if (exchanges.length > 0) {
|
|
557223
|
+
if (lines.length > 1) lines.push("");
|
|
557224
|
+
lines.push("Most recent user/assistant chronology:");
|
|
557225
|
+
for (const entry of exchanges) {
|
|
557226
|
+
const user = cleanForStorage(entry.task) || entry.task;
|
|
557227
|
+
const assistant = cleanForStorage(entry.assistantResponse || entry.summary) || entry.assistantResponse || entry.summary;
|
|
557228
|
+
if (!assistant) continue;
|
|
557229
|
+
lines.push(`- User: ${user.slice(0, 120)}`);
|
|
557230
|
+
lines.push(` Assistant: ${assistant.slice(0, 160)}`);
|
|
557231
|
+
}
|
|
557232
|
+
}
|
|
557233
|
+
return lines.length > 1 ? lines.join("\n") : "";
|
|
557012
557234
|
}
|
|
557013
557235
|
function getEnvironment(repoRoot) {
|
|
557014
557236
|
return [
|
|
@@ -564282,12 +564504,14 @@ var init_mouse_filter = __esm({
|
|
|
564282
564504
|
onScroll = null;
|
|
564283
564505
|
onActivity = null;
|
|
564284
564506
|
onPointer = null;
|
|
564507
|
+
onKeyboard = null;
|
|
564285
564508
|
flushTimer = null;
|
|
564286
|
-
constructor(scrollHandler, activityHandler, pointerHandler) {
|
|
564509
|
+
constructor(scrollHandler, activityHandler, pointerHandler, keyboardHandler) {
|
|
564287
564510
|
super();
|
|
564288
564511
|
this.onScroll = scrollHandler;
|
|
564289
564512
|
this.onActivity = activityHandler ?? null;
|
|
564290
564513
|
this.onPointer = pointerHandler ?? null;
|
|
564514
|
+
this.onKeyboard = keyboardHandler ?? null;
|
|
564291
564515
|
}
|
|
564292
564516
|
_transform(chunk, _encoding, callback) {
|
|
564293
564517
|
this.buffer += chunk.toString();
|
|
@@ -564309,7 +564533,9 @@ var init_mouse_filter = __esm({
|
|
|
564309
564533
|
else if ((btn === 65 || btn === 97) && this.onScroll) this.onScroll("down", 3, row);
|
|
564310
564534
|
else if (this.onPointer) {
|
|
564311
564535
|
const hasShift = (btn & 4) !== 0 && btn < 32;
|
|
564312
|
-
if (btn === 2
|
|
564536
|
+
if (btn === 2) {
|
|
564537
|
+
} else if (hasShift) {
|
|
564538
|
+
process.stdout.write("\x1B[?1000l\x1B[?1006l");
|
|
564313
564539
|
} else if ((btn === 0 || btn === 1) && suffix === "M") {
|
|
564314
564540
|
this.onPointer("press", col, row);
|
|
564315
564541
|
} else if (btn >= 32 && btn <= 35 && suffix === "M") {
|
|
@@ -564345,6 +564571,7 @@ var init_mouse_filter = __esm({
|
|
|
564345
564571
|
}
|
|
564346
564572
|
this.buffer = this.buffer.slice(i2);
|
|
564347
564573
|
if (output.length > 0) {
|
|
564574
|
+
if (this.onKeyboard) this.onKeyboard();
|
|
564348
564575
|
this.push(output);
|
|
564349
564576
|
}
|
|
564350
564577
|
if (this.buffer.length > 0) {
|
|
@@ -566858,11 +567085,13 @@ async function handleContextSave(ctx3) {
|
|
|
566858
567085
|
savedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
566859
567086
|
task: typeof body?.task === "string" ? body.task : typeof body?.prompt === "string" ? body.prompt : typeof body?.task_id === "string" ? body.task_id : `manual-${Date.now()}`,
|
|
566860
567087
|
summary: typeof body?.summary === "string" ? body.summary : "",
|
|
567088
|
+
assistantResponse: typeof body?.assistant_response === "string" ? body.assistant_response : "",
|
|
566861
567089
|
filesModified: Array.isArray(body?.files_modified) ? body.files_modified : [],
|
|
566862
567090
|
toolCalls: typeof body?.tool_calls === "number" ? body.tool_calls : 0,
|
|
566863
567091
|
completed: body?.completed !== false,
|
|
566864
567092
|
// default true
|
|
566865
|
-
model: typeof body?.model === "string" ? body.model : ""
|
|
567093
|
+
model: typeof body?.model === "string" ? body.model : "",
|
|
567094
|
+
source: "api"
|
|
566866
567095
|
};
|
|
566867
567096
|
saveSessionContext(repoRoot, entry);
|
|
566868
567097
|
publishEvent("session.created", { task: entry.task.slice(0, 80) }, {
|
|
@@ -579633,7 +579862,6 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
|
|
|
579633
579862
|
const modelTier = getModelTier(config.model);
|
|
579634
579863
|
const projectCtx = buildProjectContext(repoRoot, taskStores?.contextStores);
|
|
579635
579864
|
let dynamicContext = formatContextForPrompt(projectCtx, modelTier);
|
|
579636
|
-
let _autoJumpedThisStream = false;
|
|
579637
579865
|
const environmentProvider = () => {
|
|
579638
579866
|
try {
|
|
579639
579867
|
let env2 = formatSnapshotForContext(collectSnapshot(repoRoot));
|
|
@@ -580247,6 +580475,7 @@ ${entry.fullContent}`
|
|
|
580247
580475
|
let toolCallStartMs = 0;
|
|
580248
580476
|
let streamStartMs = 0;
|
|
580249
580477
|
let streamTextBuffer = "";
|
|
580478
|
+
let lastAssistantText = "";
|
|
580250
580479
|
let lastProvenancePath = null;
|
|
580251
580480
|
let showLittleman = false;
|
|
580252
580481
|
const littlemanBuffer = [];
|
|
@@ -580283,25 +580512,9 @@ ${entry.fullContent}`
|
|
|
580283
580512
|
}
|
|
580284
580513
|
if (statusBar?.isActive) {
|
|
580285
580514
|
statusBar.beginContentWrite();
|
|
580286
|
-
const alreadyBuffered = process.stdout.write.__oa_buffer_lines === true;
|
|
580287
|
-
let postInterceptWrite = null;
|
|
580288
|
-
if (!alreadyBuffered) {
|
|
580289
|
-
postInterceptWrite = process.stdout.write;
|
|
580290
|
-
const boundWrite = postInterceptWrite.bind(process.stdout);
|
|
580291
|
-
process.stdout.write = ((chunk, ...args) => {
|
|
580292
|
-
const text = typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk);
|
|
580293
|
-
for (const line of text.split("\n")) {
|
|
580294
|
-
if (line.replace(/\x1B\[[0-9;]*[A-Za-z]/g, "").length > 0) {
|
|
580295
|
-
statusBar.bufferContentLine(line);
|
|
580296
|
-
}
|
|
580297
|
-
}
|
|
580298
|
-
return boundWrite(chunk, ...args);
|
|
580299
|
-
});
|
|
580300
|
-
}
|
|
580301
580515
|
try {
|
|
580302
580516
|
fn();
|
|
580303
580517
|
} finally {
|
|
580304
|
-
if (postInterceptWrite) process.stdout.write = postInterceptWrite;
|
|
580305
580518
|
statusBar.endContentWrite();
|
|
580306
580519
|
}
|
|
580307
580520
|
} else {
|
|
@@ -580444,7 +580657,6 @@ ${entry.fullContent}`
|
|
|
580444
580657
|
case "stream_start":
|
|
580445
580658
|
streamStartMs = Date.now();
|
|
580446
580659
|
streamTextBuffer = "";
|
|
580447
|
-
_autoJumpedThisStream = false;
|
|
580448
580660
|
if (!isNeovimActive()) {
|
|
580449
580661
|
if (stream?.enabled) {
|
|
580450
580662
|
if (statusBar?.isActive) statusBar.beginContentWrite();
|
|
@@ -580463,15 +580675,6 @@ ${entry.fullContent}`
|
|
|
580463
580675
|
writeToNeovimOutput(event.content);
|
|
580464
580676
|
}
|
|
580465
580677
|
} else if (stream?.enabled) {
|
|
580466
|
-
if (statusBar?.isActive && statusBar.isScrolledBack && !_autoJumpedThisStream) {
|
|
580467
|
-
if ((event.streamKind ?? "content") === "thinking") {
|
|
580468
|
-
try {
|
|
580469
|
-
statusBar.jumpToLive();
|
|
580470
|
-
} catch {
|
|
580471
|
-
}
|
|
580472
|
-
_autoJumpedThisStream = true;
|
|
580473
|
-
}
|
|
580474
|
-
}
|
|
580475
580678
|
stream.renderer.write(
|
|
580476
580679
|
event.content ?? "",
|
|
580477
580680
|
event.streamKind ?? "content"
|
|
@@ -580584,6 +580787,10 @@ ${entry.fullContent}`
|
|
|
580584
580787
|
if (sudoCallback) sudoCallback(event.content ?? "");
|
|
580585
580788
|
break;
|
|
580586
580789
|
case "assistant_text":
|
|
580790
|
+
if (event.content) {
|
|
580791
|
+
const cleanAssistantText = cleanForStorage(event.content).trim();
|
|
580792
|
+
if (cleanAssistantText) lastAssistantText = cleanAssistantText;
|
|
580793
|
+
}
|
|
580587
580794
|
if (_apiCallbacks?.onAssistantText && event.content) {
|
|
580588
580795
|
_apiCallbacks.onAssistantText(event.content, event.turn ?? 0);
|
|
580589
580796
|
}
|
|
@@ -580792,14 +580999,17 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
580792
580999
|
} catch {
|
|
580793
581000
|
}
|
|
580794
581001
|
try {
|
|
581002
|
+
const assistantResponse = cleanForStorage(lastAssistantText || result.summary).slice(0, 1200);
|
|
580795
581003
|
saveSessionContext(repoRoot, {
|
|
580796
581004
|
savedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
580797
581005
|
task: cleanPromptForDiary(task).slice(0, 500),
|
|
580798
581006
|
summary: result.summary.slice(0, 500),
|
|
581007
|
+
assistantResponse,
|
|
580799
581008
|
filesModified: Array.from(filesTouched).slice(0, 30),
|
|
580800
581009
|
toolCalls: result.toolCalls,
|
|
580801
581010
|
completed: result.completed,
|
|
580802
|
-
model: config.model
|
|
581011
|
+
model: config.model,
|
|
581012
|
+
source: "task_complete"
|
|
580803
581013
|
});
|
|
580804
581014
|
} catch {
|
|
580805
581015
|
}
|
|
@@ -581562,7 +581772,6 @@ ${opts.systemPromptAddition}` : `Working directory: ${repoRoot}`;
|
|
|
581562
581772
|
let adminSessionKey = null;
|
|
581563
581773
|
const callSubAgents = /* @__PURE__ */ new Map();
|
|
581564
581774
|
const streamRenderer = new StreamRenderer();
|
|
581565
|
-
let _autoJumpedThisStream = false;
|
|
581566
581775
|
if (savedSettings.voice) {
|
|
581567
581776
|
if (savedSettings.voiceModel) {
|
|
581568
581777
|
voiceEngine.modelId = savedSettings.voiceModel;
|
|
@@ -581813,6 +582022,8 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
581813
582022
|
statusBar.scheduleMouseIdle();
|
|
581814
582023
|
}, (type, col, row) => {
|
|
581815
582024
|
statusBar.handlePointerEvent(type, col, row);
|
|
582025
|
+
}, () => {
|
|
582026
|
+
statusBar.enableMouseTracking();
|
|
581816
582027
|
});
|
|
581817
582028
|
process.stdin.pipe(mouseFilter);
|
|
581818
582029
|
process.stdin.on("error", (err) => {
|
|
@@ -583891,6 +584102,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
583891
584102
|
summary: `Manual context save. ${sessionToolCallCount} tool calls, ${sessionFilesTouched.length} files modified.`,
|
|
583892
584103
|
filesModified: [...sessionFilesTouched],
|
|
583893
584104
|
toolCalls: sessionToolCallCount,
|
|
584105
|
+
source: "manual",
|
|
583894
584106
|
completed: false,
|
|
583895
584107
|
model: currentConfig.model
|
|
583896
584108
|
};
|
package/package.json
CHANGED