chatroom-cli 1.81.0 → 1.82.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/index.js +261 -137
- package/dist/index.js.map +10 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -77473,6 +77473,7 @@ var init_unresolved_decisions = () => {};
|
|
|
77473
77473
|
// ../../services/backend/prompts/utils/handoff-report-template-body.ts
|
|
77474
77474
|
function getHandoffReportTemplateBody(roleGuidanceContext) {
|
|
77475
77475
|
return `<handoff-overview>
|
|
77476
|
+
<!-- For informational tasks (summaries, feedback, Q&A with no code changes): put the complete primary answer in Summary and What changed — the user only sees this handoff. -->
|
|
77476
77477
|
## Summary
|
|
77477
77478
|
<what was accomplished, in plain terms — no references to prior messages>
|
|
77478
77479
|
|
|
@@ -77834,7 +77835,7 @@ function getNativeHandoffTurnEndGuidance(nextRole) {
|
|
|
77834
77835
|
if (nextRole.toLowerCase() === "user") {
|
|
77835
77836
|
lines.push("The system delivers the next chatroom task when the user sends one.");
|
|
77836
77837
|
} else {
|
|
77837
|
-
lines.push(`The system delivers \`${nextRole}\`'s handback when they finish — do not poll \`messages
|
|
77838
|
+
lines.push(`The system delivers \`${nextRole}\`'s handback when they finish — do not poll \`messages download\` while waiting. For history reconstruction tasks, \`messages download\` is the correct tool.`);
|
|
77838
77839
|
}
|
|
77839
77840
|
return lines.join(`
|
|
77840
77841
|
`);
|
|
@@ -80525,29 +80526,19 @@ var init_skill = __esm(() => {
|
|
|
80525
80526
|
|
|
80526
80527
|
// src/commands/messages/messages-fs-service.ts
|
|
80527
80528
|
import * as nodeFs2 from "node:fs/promises";
|
|
80528
|
-
function
|
|
80529
|
+
function messageFilename(msg) {
|
|
80530
|
+
const sortPrefix = String(SORT_KEY_MAX - msg._creationTime).padStart(13, "0");
|
|
80531
|
+
const receiver = msg.targetRole ?? "all";
|
|
80532
|
+
return `${sortPrefix}_${msg.senderRole}-to-${receiver}_${msg._id}.md`;
|
|
80533
|
+
}
|
|
80534
|
+
function buildLinearMessageContent(msg) {
|
|
80529
80535
|
const ts = new Date(msg._creationTime).toISOString();
|
|
80530
|
-
const
|
|
80531
|
-
|
|
80532
|
-
|
|
80533
|
-
|
|
80534
|
-
parts2.push(`senderRole: ${msg.senderRole}`);
|
|
80535
|
-
parts2.push(`type: ${msg.type}`);
|
|
80536
|
-
if (msg.targetRole)
|
|
80537
|
-
parts2.push(`targetRole: ${msg.targetRole}`);
|
|
80538
|
-
if (msg.classification)
|
|
80539
|
-
parts2.push(`classification: ${msg.classification}`);
|
|
80540
|
-
if (msg.taskStatus)
|
|
80541
|
-
parts2.push(`taskStatus: ${msg.taskStatus}`);
|
|
80542
|
-
if (msg.featureTitle)
|
|
80543
|
-
parts2.push(`featureTitle: ${msg.featureTitle}`);
|
|
80544
|
-
parts2.push("---");
|
|
80545
|
-
parts2.push("");
|
|
80546
|
-
parts2.push(msg.content);
|
|
80547
|
-
return parts2.join(`
|
|
80548
|
-
`);
|
|
80536
|
+
const receiver = msg.targetRole ? ` → ${msg.targetRole}` : "";
|
|
80537
|
+
return `${ts} | ${msg.senderRole}${receiver}
|
|
80538
|
+
|
|
80539
|
+
${msg.content}`;
|
|
80549
80540
|
}
|
|
80550
|
-
var MessagesFsService, MessagesFsServiceLive;
|
|
80541
|
+
var MessagesFsService, MessagesFsServiceLive, SORT_KEY_MAX = 9999999999999;
|
|
80551
80542
|
var init_messages_fs_service = __esm(() => {
|
|
80552
80543
|
init_esm();
|
|
80553
80544
|
MessagesFsService = class MessagesFsService extends exports_Context.Tag("MessagesFsService")() {
|
|
@@ -80560,10 +80551,186 @@ var init_messages_fs_service = __esm(() => {
|
|
|
80560
80551
|
mkdir: (path3, opts) => exports_Effect.tryPromise({
|
|
80561
80552
|
try: () => nodeFs2.mkdir(path3, opts),
|
|
80562
80553
|
catch: (e) => e instanceof Error ? e : new Error(String(e))
|
|
80554
|
+
}),
|
|
80555
|
+
rm: (path3, opts) => exports_Effect.tryPromise({
|
|
80556
|
+
try: () => nodeFs2.rm(path3, opts),
|
|
80557
|
+
catch: (e) => e instanceof Error ? e : new Error(String(e))
|
|
80563
80558
|
})
|
|
80564
80559
|
});
|
|
80565
80560
|
});
|
|
80566
80561
|
|
|
80562
|
+
// src/commands/messages/download.ts
|
|
80563
|
+
var exports_download = {};
|
|
80564
|
+
__export(exports_download, {
|
|
80565
|
+
resolveDownloadOutputDir: () => resolveDownloadOutputDir,
|
|
80566
|
+
downloadMessagesEffect: () => downloadMessagesEffect,
|
|
80567
|
+
downloadMessages: () => downloadMessages
|
|
80568
|
+
});
|
|
80569
|
+
import * as nodePath2 from "node:path";
|
|
80570
|
+
function parseLimit(raw) {
|
|
80571
|
+
const cap = raw ?? DEFAULT_LIMIT;
|
|
80572
|
+
if (!Number.isFinite(cap) || cap < 1)
|
|
80573
|
+
return DEFAULT_LIMIT;
|
|
80574
|
+
return Math.min(Math.floor(cap), ABSOLUTE_MAX);
|
|
80575
|
+
}
|
|
80576
|
+
function resolveDownloadOutputDir(format4, cwd = process.cwd()) {
|
|
80577
|
+
const downloadId = new Date().toISOString().replace(/[:.]/g, "-");
|
|
80578
|
+
return nodePath2.resolve(cwd, ".chatroom", "downloads", "messages", format4, downloadId);
|
|
80579
|
+
}
|
|
80580
|
+
async function downloadMessages(chatroomId, options, deps) {
|
|
80581
|
+
const { getSessionId: getSessionId2, getOtherSessionUrls: getOtherSessionUrls2 } = await Promise.resolve().then(() => (init_storage(), exports_storage));
|
|
80582
|
+
const { getConvexClient: getConvexClient2, getConvexUrl: getConvexUrl2 } = await Promise.resolve().then(() => (init_client2(), exports_client));
|
|
80583
|
+
const client4 = await getConvexClient2();
|
|
80584
|
+
const actualDeps = deps ?? {
|
|
80585
|
+
backend: {
|
|
80586
|
+
mutation: (ep, args2) => client4.mutation(ep, args2),
|
|
80587
|
+
query: (ep, args2) => client4.query(ep, args2)
|
|
80588
|
+
},
|
|
80589
|
+
session: { getSessionId: getSessionId2, getConvexUrl: getConvexUrl2, getOtherSessionUrls: getOtherSessionUrls2 }
|
|
80590
|
+
};
|
|
80591
|
+
const layer = commandServicesLayerFromDeps(actualDeps);
|
|
80592
|
+
const handler = (err) => {
|
|
80593
|
+
return exports_Effect.sync(() => {
|
|
80594
|
+
if (err._tag === "NotAuthenticated") {
|
|
80595
|
+
console.error(`❌ Not authenticated`);
|
|
80596
|
+
process.exit(1);
|
|
80597
|
+
} else if (err._tag === "InvalidChatroomId") {
|
|
80598
|
+
console.error(`❌ Invalid chatroom ID`);
|
|
80599
|
+
process.exit(1);
|
|
80600
|
+
} else if (err._tag === "QueryFailed") {
|
|
80601
|
+
console.error(`
|
|
80602
|
+
❌ Error fetching messages: ${err.cause.message}`);
|
|
80603
|
+
process.exit(1);
|
|
80604
|
+
} else if (err._tag === "OutputDirError") {
|
|
80605
|
+
console.error(`
|
|
80606
|
+
❌ Failed to create output directory: ${err.cause.message}`);
|
|
80607
|
+
process.exit(1);
|
|
80608
|
+
} else if (err._tag === "WriteFailed") {
|
|
80609
|
+
console.error(`
|
|
80610
|
+
❌ Failed to write ${err.path}: ${err.cause.message}`);
|
|
80611
|
+
process.exit(1);
|
|
80612
|
+
} else {
|
|
80613
|
+
console.error(`
|
|
80614
|
+
❌ Download failed: ${err.message}`);
|
|
80615
|
+
process.exit(1);
|
|
80616
|
+
}
|
|
80617
|
+
});
|
|
80618
|
+
};
|
|
80619
|
+
await exports_Effect.runPromise(downloadMessagesEffect(chatroomId, options).pipe(exports_Effect.catchAll(handler), exports_Effect.provide(exports_Layer.mergeAll(layer, MessagesFsServiceLive))));
|
|
80620
|
+
}
|
|
80621
|
+
var PAGE_SIZE = 50, ABSOLUTE_MAX = 5000, DEFAULT_LIMIT = 10, downloadMessagesEffect = (chatroomId, options) => exports_Effect.gen(function* () {
|
|
80622
|
+
const backend2 = yield* BackendService;
|
|
80623
|
+
const fs11 = yield* MessagesFsService;
|
|
80624
|
+
const sessionId = yield* requireSessionIdEffect((a) => ({
|
|
80625
|
+
_tag: "NotAuthenticated",
|
|
80626
|
+
convexUrl: a.convexUrl,
|
|
80627
|
+
otherUrls: a.otherUrls
|
|
80628
|
+
}));
|
|
80629
|
+
yield* validateChatroomIdEffect(chatroomId, (id3) => ({
|
|
80630
|
+
_tag: "InvalidChatroomId",
|
|
80631
|
+
id: id3
|
|
80632
|
+
}));
|
|
80633
|
+
const format4 = options.format ?? "linear";
|
|
80634
|
+
const maxDownload = parseLimit(options.limit);
|
|
80635
|
+
const outputDir = options.outputDir ?? resolveDownloadOutputDir(format4);
|
|
80636
|
+
const absoluteOutputDir = nodePath2.resolve(outputDir);
|
|
80637
|
+
const messages = [];
|
|
80638
|
+
let truncated = false;
|
|
80639
|
+
let hasMore = true;
|
|
80640
|
+
const firstPageSize = Math.min(PAGE_SIZE, maxDownload);
|
|
80641
|
+
const latest = yield* backend2.query(api.messageList.getLatestMessages, { sessionId, chatroomId, limit: firstPageSize });
|
|
80642
|
+
messages.push(...latest.messages);
|
|
80643
|
+
hasMore = latest.hasMore;
|
|
80644
|
+
while (hasMore && messages.length < maxDownload) {
|
|
80645
|
+
const oldest = messages[0];
|
|
80646
|
+
if (!oldest) {
|
|
80647
|
+
hasMore = false;
|
|
80648
|
+
break;
|
|
80649
|
+
}
|
|
80650
|
+
const remaining = maxDownload - messages.length;
|
|
80651
|
+
const pageSize = Math.min(PAGE_SIZE, remaining);
|
|
80652
|
+
const batch = yield* backend2.query(api.messageList.listMessagesBefore, {
|
|
80653
|
+
sessionId,
|
|
80654
|
+
chatroomId,
|
|
80655
|
+
before: oldest._creationTime,
|
|
80656
|
+
limit: pageSize
|
|
80657
|
+
});
|
|
80658
|
+
if (batch.length === 0) {
|
|
80659
|
+
hasMore = false;
|
|
80660
|
+
break;
|
|
80661
|
+
}
|
|
80662
|
+
const space = maxDownload - messages.length;
|
|
80663
|
+
const toPrepend = batch.slice(Math.max(0, batch.length - space));
|
|
80664
|
+
for (let i2 = toPrepend.length - 1;i2 >= 0; i2--)
|
|
80665
|
+
messages.unshift(toPrepend[i2]);
|
|
80666
|
+
hasMore = batch.length >= pageSize && messages.length < maxDownload;
|
|
80667
|
+
if (messages.length >= maxDownload && (batch.length >= pageSize || latest.hasMore))
|
|
80668
|
+
truncated = true;
|
|
80669
|
+
if (toPrepend.length < batch.length)
|
|
80670
|
+
truncated = true;
|
|
80671
|
+
}
|
|
80672
|
+
const complete3 = !truncated && !hasMore;
|
|
80673
|
+
yield* fs11.rm(outputDir, { recursive: true, force: true }).pipe(exports_Effect.catchAll(() => exports_Effect.void));
|
|
80674
|
+
yield* fs11.mkdir(outputDir, { recursive: true }).pipe(exports_Effect.mapError((cause3) => ({ _tag: "OutputDirError", cause: cause3 })));
|
|
80675
|
+
const manifestEntries = [];
|
|
80676
|
+
for (const msg of messages) {
|
|
80677
|
+
const file = messageFilename(msg);
|
|
80678
|
+
const content = buildLinearMessageContent(msg);
|
|
80679
|
+
const filePath = nodePath2.join(outputDir, file);
|
|
80680
|
+
yield* fs11.writeFile(filePath, content).pipe(exports_Effect.mapError((cause3) => ({
|
|
80681
|
+
_tag: "WriteFailed",
|
|
80682
|
+
path: filePath,
|
|
80683
|
+
cause: cause3
|
|
80684
|
+
})));
|
|
80685
|
+
manifestEntries.push({
|
|
80686
|
+
id: msg._id,
|
|
80687
|
+
file,
|
|
80688
|
+
createdAt: new Date(msg._creationTime).toISOString(),
|
|
80689
|
+
senderRole: msg.senderRole,
|
|
80690
|
+
targetRole: msg.targetRole
|
|
80691
|
+
});
|
|
80692
|
+
}
|
|
80693
|
+
const manifest = {
|
|
80694
|
+
chatroomId,
|
|
80695
|
+
downloadedAt: new Date().toISOString(),
|
|
80696
|
+
count: messages.length,
|
|
80697
|
+
complete: complete3,
|
|
80698
|
+
truncated,
|
|
80699
|
+
oldestDownloadedAt: messages[0] ? new Date(messages[0]._creationTime).toISOString() : null,
|
|
80700
|
+
newestDownloadedAt: messages[messages.length - 1] ? new Date(messages[messages.length - 1]._creationTime).toISOString() : null,
|
|
80701
|
+
messages: manifestEntries
|
|
80702
|
+
};
|
|
80703
|
+
const manifestPath = nodePath2.join(outputDir, "manifest.json");
|
|
80704
|
+
yield* fs11.writeFile(manifestPath, JSON.stringify(manifest, null, 2)).pipe(exports_Effect.mapError((cause3) => ({
|
|
80705
|
+
_tag: "WriteFailed",
|
|
80706
|
+
path: manifestPath,
|
|
80707
|
+
cause: cause3
|
|
80708
|
+
})));
|
|
80709
|
+
yield* exports_Effect.sync(() => {
|
|
80710
|
+
console.log(`
|
|
80711
|
+
✅ Downloaded ${messages.length} messages to:`);
|
|
80712
|
+
console.log(` ${absoluteOutputDir}`);
|
|
80713
|
+
console.log(` complete=${complete3} truncated=${truncated}`);
|
|
80714
|
+
console.log(`
|
|
80715
|
+
\uD83D\uDCA1 Read recent history:`);
|
|
80716
|
+
console.log(` ls "${absoluteOutputDir}/"`);
|
|
80717
|
+
console.log(` cat "${absoluteOutputDir}/manifest.json"`);
|
|
80718
|
+
console.log(` rg "pattern" "${absoluteOutputDir}/"`);
|
|
80719
|
+
if (truncated) {
|
|
80720
|
+
const nextLimit = Math.min(messages.length * 2, ABSOLUTE_MAX);
|
|
80721
|
+
console.log(`
|
|
80722
|
+
\uD83D\uDCA1 Truncated — fetch more history by increasing --limit:`);
|
|
80723
|
+
console.log(` chatroom messages download --chatroom-id=${chatroomId} --role=${options.role} --format=linear --limit=${nextLimit}`);
|
|
80724
|
+
}
|
|
80725
|
+
});
|
|
80726
|
+
});
|
|
80727
|
+
var init_download = __esm(() => {
|
|
80728
|
+
init_esm();
|
|
80729
|
+
init_messages_fs_service();
|
|
80730
|
+
init_api3();
|
|
80731
|
+
init_services();
|
|
80732
|
+
});
|
|
80733
|
+
|
|
80567
80734
|
// src/commands/messages/index.ts
|
|
80568
80735
|
var exports_messages = {};
|
|
80569
80736
|
__export(exports_messages, {
|
|
@@ -80571,10 +80738,8 @@ __export(exports_messages, {
|
|
|
80571
80738
|
listSinceMessage: () => listSinceMessage,
|
|
80572
80739
|
listBySenderRoleEffect: () => listBySenderRoleEffect,
|
|
80573
80740
|
listBySenderRole: () => listBySenderRole,
|
|
80574
|
-
|
|
80575
|
-
exportMessages: () => exportMessages
|
|
80741
|
+
downloadMessages: () => downloadMessages
|
|
80576
80742
|
});
|
|
80577
|
-
import * as nodePath2 from "node:path";
|
|
80578
80743
|
async function createDefaultDeps14() {
|
|
80579
80744
|
const client4 = await getConvexClient();
|
|
80580
80745
|
return {
|
|
@@ -80645,20 +80810,6 @@ async function listSinceMessage(chatroomId, options, deps) {
|
|
|
80645
80810
|
const layer = commandServicesLayerFromDeps(d);
|
|
80646
80811
|
await exports_Effect.runPromise(listSinceMessageEffect(chatroomId, options).pipe(exports_Effect.catchAll((err) => handleMessagesError(err)), exports_Effect.provide(layer)));
|
|
80647
80812
|
}
|
|
80648
|
-
async function exportMessages(chatroomId, options, deps) {
|
|
80649
|
-
const d = deps ?? await createDefaultDeps14();
|
|
80650
|
-
const layer = commandServicesLayerFromDeps(d);
|
|
80651
|
-
await exports_Effect.runPromise(exportMessagesEffect(chatroomId, options).pipe(exports_Effect.catchAll((err) => {
|
|
80652
|
-
if ("_tag" in err) {
|
|
80653
|
-
return handleMessagesError(err);
|
|
80654
|
-
}
|
|
80655
|
-
return exports_Effect.sync(() => {
|
|
80656
|
-
console.error(`
|
|
80657
|
-
❌ Export failed: ${err.message}`);
|
|
80658
|
-
process.exit(1);
|
|
80659
|
-
});
|
|
80660
|
-
}), exports_Effect.provide(exports_Layer.mergeAll(layer, MessagesFsServiceLive))));
|
|
80661
|
-
}
|
|
80662
80813
|
var listBySenderRoleEffect = (chatroomId, options) => exports_Effect.gen(function* () {
|
|
80663
80814
|
const backend2 = yield* BackendService;
|
|
80664
80815
|
const sessionId = yield* requireSessionIdEffect((a) => ({
|
|
@@ -80749,63 +80900,14 @@ ${roleIndicator} ${message.senderRole}${message.targetRole ? ` → ${message.tar
|
|
|
80749
80900
|
` + "─".repeat(60));
|
|
80750
80901
|
console.log(`\uD83D\uDCA1 Use --full to see complete message content`);
|
|
80751
80902
|
});
|
|
80752
|
-
}), exportMessagesEffect = (chatroomId, options) => exports_Effect.gen(function* () {
|
|
80753
|
-
const backend2 = yield* BackendService;
|
|
80754
|
-
const fs11 = yield* MessagesFsService;
|
|
80755
|
-
const sessionId = yield* requireSessionIdEffect((a) => ({
|
|
80756
|
-
_tag: "NotAuthenticated",
|
|
80757
|
-
convexUrl: a.convexUrl,
|
|
80758
|
-
otherUrls: a.otherUrls
|
|
80759
|
-
}));
|
|
80760
|
-
yield* validateChatroomIdEffect(chatroomId, (id3) => ({
|
|
80761
|
-
_tag: "InvalidChatroomId",
|
|
80762
|
-
id: id3
|
|
80763
|
-
}));
|
|
80764
|
-
const messagesResult = yield* exports_Effect.either(backend2.query(api.messages.listBySenderRole, {
|
|
80765
|
-
sessionId,
|
|
80766
|
-
chatroomId,
|
|
80767
|
-
senderRole: options.senderRole || "planner",
|
|
80768
|
-
limit: options.limit
|
|
80769
|
-
}));
|
|
80770
|
-
if (messagesResult._tag === "Left") {
|
|
80771
|
-
return yield* exports_Effect.fail({
|
|
80772
|
-
_tag: "QueryFailed",
|
|
80773
|
-
cause: messagesResult.left
|
|
80774
|
-
});
|
|
80775
|
-
}
|
|
80776
|
-
const messages = messagesResult.right;
|
|
80777
|
-
if (messages.length === 0) {
|
|
80778
|
-
yield* exports_Effect.sync(() => console.log("No messages to export."));
|
|
80779
|
-
return;
|
|
80780
|
-
}
|
|
80781
|
-
const dir = options.exportPath || `.chatroom/exports/messages/${chatroomId}`;
|
|
80782
|
-
yield* fs11.mkdir(dir, { recursive: true });
|
|
80783
|
-
const manifest = [];
|
|
80784
|
-
for (const msg of messages) {
|
|
80785
|
-
const filename = `${msg._creationTime}-${msg.senderRole}-${msg._id.slice(0, 8)}.md`;
|
|
80786
|
-
const markdown = buildMessageMarkdown(msg);
|
|
80787
|
-
yield* fs11.writeFile(nodePath2.join(dir, filename), markdown);
|
|
80788
|
-
manifest.push({
|
|
80789
|
-
id: msg._id,
|
|
80790
|
-
senderRole: msg.senderRole,
|
|
80791
|
-
createdAt: msg._creationTime,
|
|
80792
|
-
filename
|
|
80793
|
-
});
|
|
80794
|
-
}
|
|
80795
|
-
yield* fs11.writeFile(nodePath2.join(dir, "manifest.json"), JSON.stringify(manifest, null, 2));
|
|
80796
|
-
yield* exports_Effect.sync(() => {
|
|
80797
|
-
console.log(`
|
|
80798
|
-
\uD83D\uDCE8 Exported ${messages.length} messages to ${dir}`);
|
|
80799
|
-
console.log(` Manifest: ${dir}/manifest.json`);
|
|
80800
|
-
});
|
|
80801
80903
|
});
|
|
80802
80904
|
var init_messages = __esm(() => {
|
|
80803
80905
|
init_esm();
|
|
80804
|
-
init_messages_fs_service();
|
|
80805
80906
|
init_api3();
|
|
80806
80907
|
init_storage();
|
|
80807
80908
|
init_client2();
|
|
80808
80909
|
init_services();
|
|
80910
|
+
init_download();
|
|
80809
80911
|
});
|
|
80810
80912
|
|
|
80811
80913
|
// src/commands/context/format-new-context-error.ts
|
|
@@ -97229,7 +97331,7 @@ async function emitPhase(deps, event, phase, detail) {
|
|
|
97229
97331
|
});
|
|
97230
97332
|
}
|
|
97231
97333
|
function sleep5(ms) {
|
|
97232
|
-
return new Promise((
|
|
97334
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
97233
97335
|
}
|
|
97234
97336
|
async function waitForHarnessSessionId(deps, event, pid) {
|
|
97235
97337
|
const initial = deps.agentMgr.getSlot(event.chatroomId, event.role);
|
|
@@ -97741,19 +97843,19 @@ class ProcessManager {
|
|
|
97741
97843
|
this.pendingStops.clear();
|
|
97742
97844
|
}
|
|
97743
97845
|
waitForExit(runId, ms) {
|
|
97744
|
-
return new Promise((
|
|
97846
|
+
return new Promise((resolve5) => {
|
|
97745
97847
|
const interval = 100;
|
|
97746
97848
|
let elapsed3 = 0;
|
|
97747
97849
|
const timer = setInterval(() => {
|
|
97748
97850
|
if (!this.runningProcesses.has(runId)) {
|
|
97749
97851
|
clearInterval(timer);
|
|
97750
|
-
|
|
97852
|
+
resolve5(true);
|
|
97751
97853
|
return;
|
|
97752
97854
|
}
|
|
97753
97855
|
elapsed3 += interval;
|
|
97754
97856
|
if (elapsed3 >= ms) {
|
|
97755
97857
|
clearInterval(timer);
|
|
97756
|
-
|
|
97858
|
+
resolve5(false);
|
|
97757
97859
|
}
|
|
97758
97860
|
}, interval);
|
|
97759
97861
|
});
|
|
@@ -97884,7 +97986,7 @@ var init_log_observer_sync = __esm(() => {
|
|
|
97884
97986
|
});
|
|
97885
97987
|
|
|
97886
97988
|
// src/commands/machine/daemon-start/handlers/process/output-store.ts
|
|
97887
|
-
import { appendFile as appendFile2, mkdir as mkdir8, readFile as readFile6, rm } from "node:fs/promises";
|
|
97989
|
+
import { appendFile as appendFile2, mkdir as mkdir8, readFile as readFile6, rm as rm2 } from "node:fs/promises";
|
|
97888
97990
|
import { tmpdir } from "node:os";
|
|
97889
97991
|
import { join as join17 } from "node:path";
|
|
97890
97992
|
|
|
@@ -97941,7 +98043,7 @@ class TempFileOutputStore {
|
|
|
97941
98043
|
}
|
|
97942
98044
|
async destroy() {
|
|
97943
98045
|
try {
|
|
97944
|
-
await
|
|
98046
|
+
await rm2(this.state.filePath, { force: true });
|
|
97945
98047
|
} catch {}
|
|
97946
98048
|
}
|
|
97947
98049
|
}
|
|
@@ -97957,7 +98059,7 @@ async function ensureTempDir() {
|
|
|
97957
98059
|
}
|
|
97958
98060
|
async function cleanOrphanTempFiles() {
|
|
97959
98061
|
try {
|
|
97960
|
-
await
|
|
98062
|
+
await rm2(TEMP_DIR, { recursive: true, force: true });
|
|
97961
98063
|
} catch {}
|
|
97962
98064
|
}
|
|
97963
98065
|
var TAIL_WINDOW_BYTES, TEMP_DIR, RUN_ID_RE, MAX_TAIL_LINES_V2 = 50;
|
|
@@ -98323,8 +98425,8 @@ var init_command_runner = __esm(() => {
|
|
|
98323
98425
|
}).catch((err) => {
|
|
98324
98426
|
console.warn(`[${formatTimestamp()}] ⚠️ Failed to mark run as killed on shutdown: ${getErrorMessage(err)}`);
|
|
98325
98427
|
})));
|
|
98326
|
-
yield* exports_Effect.promise(() => new Promise((
|
|
98327
|
-
const t = setTimeout(
|
|
98428
|
+
yield* exports_Effect.promise(() => new Promise((resolve5) => {
|
|
98429
|
+
const t = setTimeout(resolve5, 3000);
|
|
98328
98430
|
t.unref?.();
|
|
98329
98431
|
}));
|
|
98330
98432
|
for (const [, tracked] of trackedEntries) {
|
|
@@ -98336,8 +98438,8 @@ var init_command_runner = __esm(() => {
|
|
|
98336
98438
|
clearTrackedPids();
|
|
98337
98439
|
yield* exports_Effect.promise(() => Promise.race([
|
|
98338
98440
|
statusUpdates,
|
|
98339
|
-
new Promise((
|
|
98340
|
-
const t = setTimeout(
|
|
98441
|
+
new Promise((resolve5) => {
|
|
98442
|
+
const t = setTimeout(resolve5, 2000);
|
|
98341
98443
|
t.unref?.();
|
|
98342
98444
|
})
|
|
98343
98445
|
]));
|
|
@@ -98474,10 +98576,10 @@ function resolveWhichCommand(name) {
|
|
|
98474
98576
|
return process.platform === "win32" ? `where ${name}` : `which ${name}`;
|
|
98475
98577
|
}
|
|
98476
98578
|
function isCliAvailable(cliName) {
|
|
98477
|
-
return new Promise((
|
|
98579
|
+
return new Promise((resolve5) => {
|
|
98478
98580
|
const child = spawn5(resolveWhichCommand(cliName), [], DETACHED_SHELL_SPAWN_OPTIONS);
|
|
98479
|
-
child.on("error", () =>
|
|
98480
|
-
child.on("close", (code2) =>
|
|
98581
|
+
child.on("error", () => resolve5(false));
|
|
98582
|
+
child.on("close", (code2) => resolve5(code2 === 0));
|
|
98481
98583
|
child.unref();
|
|
98482
98584
|
});
|
|
98483
98585
|
}
|
|
@@ -98762,7 +98864,7 @@ async function waitForLockOrTimeout(deadline, intervalMs, sleep6) {
|
|
|
98762
98864
|
async function acquireLockWithRetry(options) {
|
|
98763
98865
|
const intervalMs = options?.intervalMs ?? LOCK_RETRY_INTERVAL_MS;
|
|
98764
98866
|
const maxWaitMs = options?.maxWaitMs ?? LOCK_RETRY_MAX_WAIT_MS;
|
|
98765
|
-
const sleep6 = options?.sleep ?? ((ms) => new Promise((
|
|
98867
|
+
const sleep6 = options?.sleep ?? ((ms) => new Promise((resolve5) => setTimeout(resolve5, ms)));
|
|
98766
98868
|
const deadline = Date.now() + maxWaitMs;
|
|
98767
98869
|
if (await waitForLockOrTimeout(deadline, intervalMs, sleep6)) {
|
|
98768
98870
|
return true;
|
|
@@ -99468,14 +99570,14 @@ var init_sse_event_buffer = __esm(() => {
|
|
|
99468
99570
|
}
|
|
99469
99571
|
_wake() {
|
|
99470
99572
|
if (this._waiter) {
|
|
99471
|
-
const
|
|
99573
|
+
const resolve5 = this._waiter;
|
|
99472
99574
|
this._waiter = null;
|
|
99473
|
-
|
|
99575
|
+
resolve5();
|
|
99474
99576
|
}
|
|
99475
99577
|
}
|
|
99476
99578
|
_waitForData() {
|
|
99477
|
-
return new Promise((
|
|
99478
|
-
this._waiter =
|
|
99579
|
+
return new Promise((resolve5) => {
|
|
99580
|
+
this._waiter = resolve5;
|
|
99479
99581
|
});
|
|
99480
99582
|
}
|
|
99481
99583
|
[Symbol.asyncIterator]() {
|
|
@@ -99530,8 +99632,8 @@ class OpencodeSdkSession {
|
|
|
99530
99632
|
async prompt(input) {
|
|
99531
99633
|
if (this.closed)
|
|
99532
99634
|
throw new Error("Session is closed");
|
|
99533
|
-
const idlePromise = new Promise((
|
|
99534
|
-
this._idleResolve =
|
|
99635
|
+
const idlePromise = new Promise((resolve5) => {
|
|
99636
|
+
this._idleResolve = resolve5;
|
|
99535
99637
|
});
|
|
99536
99638
|
const IDLE_TIMEOUT_MS = 300000;
|
|
99537
99639
|
const timeoutPromise = new Promise((_, reject) => {
|
|
@@ -99862,14 +99964,14 @@ class OpencodeSdkHarness {
|
|
|
99862
99964
|
}
|
|
99863
99965
|
this.sessionListeners.clear();
|
|
99864
99966
|
this.childProcess.kill("SIGTERM");
|
|
99865
|
-
await new Promise((
|
|
99967
|
+
await new Promise((resolve5) => {
|
|
99866
99968
|
const timeout3 = setTimeout(() => {
|
|
99867
99969
|
this.childProcess.kill("SIGKILL");
|
|
99868
|
-
|
|
99970
|
+
resolve5();
|
|
99869
99971
|
}, 5000);
|
|
99870
99972
|
this.childProcess.once("exit", () => {
|
|
99871
99973
|
clearTimeout(timeout3);
|
|
99872
|
-
|
|
99974
|
+
resolve5();
|
|
99873
99975
|
});
|
|
99874
99976
|
});
|
|
99875
99977
|
}
|
|
@@ -101303,10 +101405,10 @@ class BufferedJournalFactory {
|
|
|
101303
101405
|
const waitForInProgress = () => {
|
|
101304
101406
|
if (!flushInProgress)
|
|
101305
101407
|
return Promise.resolve();
|
|
101306
|
-
return new Promise((
|
|
101408
|
+
return new Promise((resolve5) => {
|
|
101307
101409
|
const check4 = () => {
|
|
101308
101410
|
if (!flushInProgress)
|
|
101309
|
-
|
|
101411
|
+
resolve5();
|
|
101310
101412
|
else
|
|
101311
101413
|
setTimeout(check4, 10);
|
|
101312
101414
|
};
|
|
@@ -101866,11 +101968,11 @@ async function waitForEnhancerJobResolution(params) {
|
|
|
101866
101968
|
outcome = "failed";
|
|
101867
101969
|
onFailure("Agent process exited without completing enhancer job", false);
|
|
101868
101970
|
});
|
|
101869
|
-
await new Promise((
|
|
101971
|
+
await new Promise((resolve5) => {
|
|
101870
101972
|
const check4 = setInterval(() => {
|
|
101871
101973
|
if (outcome) {
|
|
101872
101974
|
clearInterval(check4);
|
|
101873
|
-
|
|
101975
|
+
resolve5();
|
|
101874
101976
|
}
|
|
101875
101977
|
}, 100);
|
|
101876
101978
|
});
|
|
@@ -102148,7 +102250,7 @@ var init_assert_registered_working_dir = __esm(() => {
|
|
|
102148
102250
|
|
|
102149
102251
|
// src/infrastructure/services/workspace/workspace-path-security.ts
|
|
102150
102252
|
import { realpath as realpath2 } from "node:fs/promises";
|
|
102151
|
-
import { basename, dirname as dirname8, isAbsolute, relative, resolve as
|
|
102253
|
+
import { basename, dirname as dirname8, isAbsolute, relative, resolve as resolve5, sep } from "node:path";
|
|
102152
102254
|
import { gunzipSync as gunzipSync2 } from "node:zlib";
|
|
102153
102255
|
function validateRelativePathSegments(filePath) {
|
|
102154
102256
|
if (filePath.includes("\x00"))
|
|
@@ -102175,11 +102277,11 @@ async function resolvePathWithinWorkspace(workingDir, filePath) {
|
|
|
102175
102277
|
return basic;
|
|
102176
102278
|
let workspaceRoot;
|
|
102177
102279
|
try {
|
|
102178
|
-
workspaceRoot = await realpath2(
|
|
102280
|
+
workspaceRoot = await realpath2(resolve5(workingDir));
|
|
102179
102281
|
} catch {
|
|
102180
102282
|
return { ok: false, error: "Working directory not found" };
|
|
102181
102283
|
}
|
|
102182
|
-
const candidate =
|
|
102284
|
+
const candidate = resolve5(workspaceRoot, filePath);
|
|
102183
102285
|
if (!isPathInsideRoot(workspaceRoot, candidate)) {
|
|
102184
102286
|
return { ok: false, error: "Path escapes workspace" };
|
|
102185
102287
|
}
|
|
@@ -102201,7 +102303,7 @@ async function resolvePathWithinWorkspace(workingDir, filePath) {
|
|
|
102201
102303
|
if (!isPathInsideRoot(workspaceRoot, parentReal)) {
|
|
102202
102304
|
return { ok: false, error: "Path escapes workspace" };
|
|
102203
102305
|
}
|
|
102204
|
-
const resolved =
|
|
102306
|
+
const resolved = resolve5(parentReal, basename(candidate));
|
|
102205
102307
|
if (!isPathInsideRoot(workspaceRoot, resolved)) {
|
|
102206
102308
|
return { ok: false, error: "Path escapes workspace" };
|
|
102207
102309
|
}
|
|
@@ -104125,7 +104227,7 @@ class NodeFsHandler {
|
|
|
104125
104227
|
this._addToNodeFs(path6, initialAdd, wh, depth + 1);
|
|
104126
104228
|
}
|
|
104127
104229
|
}).on(EV.ERROR, this._boundHandleError);
|
|
104128
|
-
return new Promise((
|
|
104230
|
+
return new Promise((resolve7, reject) => {
|
|
104129
104231
|
if (!stream4)
|
|
104130
104232
|
return reject();
|
|
104131
104233
|
stream4.once(STR_END, () => {
|
|
@@ -104134,7 +104236,7 @@ class NodeFsHandler {
|
|
|
104134
104236
|
return;
|
|
104135
104237
|
}
|
|
104136
104238
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
104137
|
-
|
|
104239
|
+
resolve7(undefined);
|
|
104138
104240
|
previous.getChildren().filter((item) => {
|
|
104139
104241
|
return item !== directory && !current.has(item);
|
|
104140
104242
|
}).forEach((item) => {
|
|
@@ -105352,8 +105454,8 @@ function createWorkspaceFsWatcher(options) {
|
|
|
105352
105454
|
awaitWriteFinish: { stabilityThreshold: 150, pollInterval: 25 }
|
|
105353
105455
|
});
|
|
105354
105456
|
watcher.on("add", (filePath) => enqueue("add", filePath)).on("addDir", (filePath) => enqueue("addDir", filePath)).on("change", (filePath) => enqueue("change", filePath)).on("unlink", (filePath) => enqueue("unlink", filePath)).on("unlinkDir", (filePath) => enqueue("unlinkDir", filePath)).on("error", (error51) => options.onError?.(error51));
|
|
105355
|
-
const ready = new Promise((
|
|
105356
|
-
watcher.once("ready",
|
|
105457
|
+
const ready = new Promise((resolve8) => {
|
|
105458
|
+
watcher.once("ready", resolve8);
|
|
105357
105459
|
});
|
|
105358
105460
|
return {
|
|
105359
105461
|
ready,
|
|
@@ -105978,7 +106080,7 @@ function unsupportedFileWriteOperationMessage(operation) {
|
|
|
105978
106080
|
}
|
|
105979
106081
|
|
|
105980
106082
|
// src/commands/machine/daemon-start/file-write-fulfillment.ts
|
|
105981
|
-
import { access as access4, mkdir as mkdir10, rename as rename4, rm as
|
|
106083
|
+
import { access as access4, mkdir as mkdir10, rename as rename4, rm as rm4, writeFile as writeFile9 } from "node:fs/promises";
|
|
105982
106084
|
import { dirname as dirname11 } from "node:path";
|
|
105983
106085
|
function isTerminalFileWriteError(errorMessage) {
|
|
105984
106086
|
const terminalMessages = new Set([
|
|
@@ -106132,7 +106234,7 @@ async function fulfillOneFileWriteRequest(session2, request2) {
|
|
|
106132
106234
|
});
|
|
106133
106235
|
return;
|
|
106134
106236
|
}
|
|
106135
|
-
await
|
|
106237
|
+
await rm4(resolved.absolutePath, { recursive: true, force: false });
|
|
106136
106238
|
await completeWriteRequest(session2, request2._id, { status: "done" });
|
|
106137
106239
|
const elapsed4 = Date.now() - startTime;
|
|
106138
106240
|
console.log(`[${formatTimestamp()}] ✏️ File delete fulfilled: ${filePath} (${elapsed4}ms)`);
|
|
@@ -109544,7 +109646,7 @@ function createDefaultDeps19() {
|
|
|
109544
109646
|
},
|
|
109545
109647
|
clock: {
|
|
109546
109648
|
now: () => Date.now(),
|
|
109547
|
-
delay: (ms) => new Promise((
|
|
109649
|
+
delay: (ms) => new Promise((resolve8) => setTimeout(resolve8, ms))
|
|
109548
109650
|
},
|
|
109549
109651
|
spawning: new HarnessSpawningService({ rateLimiter: new SpawnRateLimiter }),
|
|
109550
109652
|
agentProcessManager: null
|
|
@@ -110909,7 +111011,7 @@ var init_jsonc = __esm(() => {
|
|
|
110909
111011
|
|
|
110910
111012
|
// src/infrastructure/services/workspace/workspace-resolver.ts
|
|
110911
111013
|
import { readFile as readFile10, readdir as readdir3, stat as stat6 } from "node:fs/promises";
|
|
110912
|
-
import { join as join22, basename as basename4, resolve as
|
|
111014
|
+
import { join as join22, basename as basename4, resolve as resolve8 } from "node:path";
|
|
110913
111015
|
async function resolveGlobPatternStar(rootDir, cleaned) {
|
|
110914
111016
|
const parentDir = join22(rootDir, cleaned.slice(0, -2));
|
|
110915
111017
|
try {
|
|
@@ -110919,7 +111021,7 @@ async function resolveGlobPatternStar(rootDir, cleaned) {
|
|
|
110919
111021
|
if (!entry.isDirectory())
|
|
110920
111022
|
continue;
|
|
110921
111023
|
const dirPath = join22(parentDir, entry.name);
|
|
110922
|
-
if (
|
|
111024
|
+
if (resolve8(dirPath).startsWith(resolve8(rootDir))) {
|
|
110923
111025
|
dirs.push(dirPath);
|
|
110924
111026
|
}
|
|
110925
111027
|
}
|
|
@@ -110931,7 +111033,7 @@ async function resolveGlobPatternStar(rootDir, cleaned) {
|
|
|
110931
111033
|
async function resolveLiteralPath(rootDir, cleaned) {
|
|
110932
111034
|
const dir = join22(rootDir, cleaned);
|
|
110933
111035
|
try {
|
|
110934
|
-
if (!
|
|
111036
|
+
if (!resolve8(dir).startsWith(resolve8(rootDir)))
|
|
110935
111037
|
return [];
|
|
110936
111038
|
const s = await stat6(dir);
|
|
110937
111039
|
if (s.isDirectory())
|
|
@@ -111808,7 +111910,7 @@ var init_layers = __esm(() => {
|
|
|
111808
111910
|
IntervalClock = class IntervalClock extends exports_Context.Tag("IntervalClock")() {
|
|
111809
111911
|
};
|
|
111810
111912
|
IntervalClockLive = exports_Layer.succeed(IntervalClock, {
|
|
111811
|
-
sleep: (ms) => exports_Effect.promise(() => new Promise((
|
|
111913
|
+
sleep: (ms) => exports_Effect.promise(() => new Promise((resolve9) => setTimeout(resolve9, ms)))
|
|
111812
111914
|
});
|
|
111813
111915
|
});
|
|
111814
111916
|
|
|
@@ -112910,8 +113012,8 @@ var init_command_loop = __esm(() => {
|
|
|
112910
113012
|
const withTimeout2 = async (p, ms) => {
|
|
112911
113013
|
await Promise.race([
|
|
112912
113014
|
Promise.resolve(p).catch(() => {}),
|
|
112913
|
-
new Promise((
|
|
112914
|
-
const t = setTimeout(
|
|
113015
|
+
new Promise((resolve9) => {
|
|
113016
|
+
const t = setTimeout(resolve9, ms);
|
|
112915
113017
|
t.unref?.();
|
|
112916
113018
|
})
|
|
112917
113019
|
]);
|
|
@@ -113076,7 +113178,7 @@ async function daemonStop() {
|
|
|
113076
113178
|
console.log(`Stopping daemon (PID: ${pid})...`);
|
|
113077
113179
|
try {
|
|
113078
113180
|
process.kill(pid, "SIGTERM");
|
|
113079
|
-
await new Promise((
|
|
113181
|
+
await new Promise((resolve9) => setTimeout(resolve9, 8000));
|
|
113080
113182
|
try {
|
|
113081
113183
|
process.kill(pid, 0);
|
|
113082
113184
|
console.log(`Process did not exit gracefully, forcing...`);
|
|
@@ -113645,7 +113747,7 @@ async function withRetry(fn2, opts) {
|
|
|
113645
113747
|
return;
|
|
113646
113748
|
}
|
|
113647
113749
|
const delay3 = Math.min(baseDelayMs * 2 ** attempt, maxDelayMs);
|
|
113648
|
-
await new Promise((
|
|
113750
|
+
await new Promise((resolve9) => setTimeout(resolve9, delay3));
|
|
113649
113751
|
}
|
|
113650
113752
|
}
|
|
113651
113753
|
return;
|
|
@@ -114032,6 +114134,28 @@ messagesCommand.command("list").description("List messages by sender role or sin
|
|
|
114032
114134
|
});
|
|
114033
114135
|
}
|
|
114034
114136
|
});
|
|
114137
|
+
messagesCommand.command("download").description("Download chatroom message history to local files for reading/grep").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").option("--format <format>", "Download format (default: linear)", "linear").option("--output-dir <path>", "Output directory (default: .chatroom/downloads/messages/linear/<download-id>)").option("--limit <n>", "Max messages to download (default: 10, max: 5000)").action(async (options) => {
|
|
114138
|
+
await maybeRequireAuth();
|
|
114139
|
+
if (options.format && options.format !== "linear") {
|
|
114140
|
+
console.error("❌ Unsupported format. Only --format=linear is supported.");
|
|
114141
|
+
process.exit(1);
|
|
114142
|
+
}
|
|
114143
|
+
let parsedLimit;
|
|
114144
|
+
if (options.limit) {
|
|
114145
|
+
parsedLimit = parseInt(options.limit, 10);
|
|
114146
|
+
if (isNaN(parsedLimit) || parsedLimit < 1) {
|
|
114147
|
+
console.error("❌ --limit must be a positive integer (1-5000)");
|
|
114148
|
+
process.exit(1);
|
|
114149
|
+
}
|
|
114150
|
+
}
|
|
114151
|
+
const { downloadMessages: downloadMessages2 } = await Promise.resolve().then(() => (init_download(), exports_download));
|
|
114152
|
+
await downloadMessages2(options.chatroomId, {
|
|
114153
|
+
role: options.role,
|
|
114154
|
+
format: "linear",
|
|
114155
|
+
outputDir: options.outputDir,
|
|
114156
|
+
limit: parsedLimit
|
|
114157
|
+
});
|
|
114158
|
+
});
|
|
114035
114159
|
var contextCommand = program2.command("context").description("Manage chatroom context and state (explicit context management)");
|
|
114036
114160
|
contextCommand.command("read").description("Read context for your role (conversation history, tasks, status)").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").action(async (options) => {
|
|
114037
114161
|
await maybeRequireAuth();
|
|
@@ -114177,4 +114301,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
114177
114301
|
});
|
|
114178
114302
|
program2.parse();
|
|
114179
114303
|
|
|
114180
|
-
//# debugId=
|
|
114304
|
+
//# debugId=7AA8EA8DC834B0AF64756E2164756E21
|