replicas-engine 0.1.580 → 0.1.582
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/src/index.js +180 -58
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -1434,6 +1434,7 @@ GitHub does NOT have a public API for uploading images to PRs/issues. When you n
|
|
|
1434
1434
|
- Do NOT use placeholder image URLs
|
|
1435
1435
|
- Do NOT commit screenshots as files to the repository
|
|
1436
1436
|
- Run \`replicas media upload <image> --name "<display name>" --share\` and put the printed \`Forge embed\` Markdown in the PR body or comment
|
|
1437
|
+
- For a self-contained HTML report, run \`replicas media upload <page.html> --name "<display name>" --access organization\` and put the printed \`Forge link\` Markdown in the PR body or comment. Organization members who are already signed in open it directly; others sign in and return to the page
|
|
1437
1438
|
- For video, embed a shared poster image linked to the recording's **View in Replicas** URL; GitHub does not reliably render externally hosted video inline
|
|
1438
1439
|
- Treat the public URL as an opt-in bearer capability; revoke it with \`replicas media revoke <media-id>\` only when the user asks or the media should stop rendering \u2014 revoking breaks embeds already posted on the PR
|
|
1439
1440
|
- If you were triggered from Slack, also upload the image to the Slack thread so the user can see it directly
|
|
@@ -2035,17 +2036,18 @@ var LINEAR_ABILITY = {
|
|
|
2035
2036
|
|
|
2036
2037
|
// ../shared/src/default-skills/replicas-agent/abilities/media.ts
|
|
2037
2038
|
var SECTION8 = `### Media
|
|
2038
|
-
Share screenshots, screen recordings, generated diagrams,
|
|
2039
|
+
Share screenshots, screen recordings, generated diagrams, audio clips, and self-contained HTML pages through Replicas and external messages.
|
|
2039
2040
|
|
|
2040
2041
|
**Reference:** \`references/MEDIA.md\`
|
|
2041
2042
|
|
|
2042
2043
|
Use this when:
|
|
2043
2044
|
- You produce a screenshot, recording, generated image, or audio clip the user should see
|
|
2045
|
+
- You produce a self-contained HTML report that should be linked from a pull request
|
|
2044
2046
|
- You record video output (browser automation, screen capture) \u2014 including the recommended aspect ratio and FPS
|
|
2045
2047
|
- You need to embed media in a Slack/Linear/GitHub message AND keep a referenceable copy in the Replicas dashboard`;
|
|
2046
|
-
var REFERENCE8 = `# Media (Screenshots, Recordings, Audio)
|
|
2048
|
+
var REFERENCE8 = `# Media (Screenshots, Recordings, Audio, HTML)
|
|
2047
2049
|
|
|
2048
|
-
This guide covers how to share screenshots, screen recordings, generated diagrams,
|
|
2050
|
+
This guide covers how to share screenshots, screen recordings, generated diagrams, audio clips, and self-contained HTML pages through Replicas and external surfaces (Slack, Linear, GitHub).
|
|
2049
2051
|
|
|
2050
2052
|
## Prerequisites
|
|
2051
2053
|
|
|
@@ -2056,7 +2058,7 @@ The \`replicas\` CLI is pre-installed and authenticated in your workspace. No ad
|
|
|
2056
2058
|
Upload to Replicas in these cases \u2014 and **only** these cases:
|
|
2057
2059
|
|
|
2058
2060
|
1. **Media you produce.** Any screenshot, screen recording, generated diagram, or audio clip you create that the user might want to see. Upload before doing anything else with the file (analyzing, deleting, sending elsewhere). This applies even when you're also sending the file to Slack, Linear, GitHub, etc.
|
|
2059
|
-
2. **Files the user explicitly asks you to upload.** If the user sends or points at a file (image, video, audio) and asks you to upload it, run \`replicas media upload\`. Otherwise leave it alone \u2014 files in the workspace the user did not ask about should not be auto-uploaded as media.
|
|
2061
|
+
2. **Files the user explicitly asks you to upload.** If the user sends or points at a file (image, video, audio, HTML) and asks you to upload it, run \`replicas media upload\`. Otherwise leave it alone \u2014 files in the workspace the user did not ask about should not be auto-uploaded as media.
|
|
2060
2062
|
3. **Anything you plan to share externally (Slack, Linear, GitHub, etc.).** Upload to Replicas *in addition to* the platform's native upload. Never as a replacement.
|
|
2061
2063
|
|
|
2062
2064
|
If none of these apply, don't upload.
|
|
@@ -2085,28 +2087,39 @@ replicas media upload /tmp/before.png /tmp/after.png --name "Before fix" --name
|
|
|
2085
2087
|
|
|
2086
2088
|
Names are normalized to hyphen-case (spaces become hyphens, e.g. \`Login page\` is stored as \`login-page\`). Give every asset a **distinct** name \u2014 duplicates are not rejected, but Replicas keeps the first as-is and adds a \`-1\`, \`-2\` suffix to later collisions, which produces confusing lists, so pick unique names yourself.
|
|
2087
2089
|
|
|
2088
|
-
For each file, the CLI prints two lines:
|
|
2090
|
+
For each media file, the CLI prints two lines:
|
|
2089
2091
|
|
|
2090
2092
|
1. \`\` \u2014 the chat embed (renders inline in Replicas chat **only** \u2014 see below).
|
|
2091
2093
|
2. \`View in Replicas: <deep-link>\` \u2014 a per-file dashboard URL of the form \`https://tryreplicas.com/workspaces/<workspace-id>?media=<media-id>\` that opens directly to that specific file.
|
|
2092
2094
|
|
|
2093
2095
|
Match each "View in Replicas" line to the embed line directly above it \u2014 that's the deep link for that file.
|
|
2094
2096
|
|
|
2095
|
-
|
|
2097
|
+
HTML uploads print an \`HTML page\` Markdown link instead of an image embed.
|
|
2098
|
+
|
|
2099
|
+
For an HTML page that should stay inside the Replicas organization, create an authenticated link:
|
|
2096
2100
|
|
|
2097
2101
|
\`\`\`bash
|
|
2098
|
-
replicas media upload
|
|
2102
|
+
replicas media upload recap.html --name "Visual recap" --access organization
|
|
2099
2103
|
\`\`\`
|
|
2100
2104
|
|
|
2101
|
-
|
|
2105
|
+
The printed \`Forge link (organization only)\` opens a dedicated page. Signed-in organization members go straight to it; signed-out members sign in and return to the page.
|
|
2106
|
+
|
|
2107
|
+
Use public access only when the media must render without Replicas authentication:
|
|
2102
2108
|
|
|
2103
|
-
|
|
2109
|
+
\`\`\`bash
|
|
2110
|
+
replicas media upload screenshot.png --name "Login page" --access public
|
|
2111
|
+
\`\`\`
|
|
2112
|
+
|
|
2113
|
+
\`--share\` remains an alias for \`--access public\`. Public access prints an additional \`Forge embed\` for media or \`Forge link\` for HTML, backed by an opt-in bearer URL. Anyone with that unguessable URL can view the asset until it is rotated or revoked. Use \`replicas media share <media-id>\` to rotate it and \`replicas media revoke <media-id>\` to revoke it.
|
|
2114
|
+
|
|
2115
|
+
## The URLs the CLI gives you \u2014 and where each one is allowed
|
|
2104
2116
|
|
|
2105
2117
|
| URL | What it is | Where it's allowed |
|
|
2106
2118
|
|---|---|---|
|
|
2107
2119
|
| \`https://api.tryreplicas.com/v1/media/<id>\` (inside \`\`) | Authenticated API redirect to a presigned blob \u2014 requires the Replicas chat session | **Only** in the Replicas chat reply. Nowhere else. |
|
|
2108
|
-
| \`https://
|
|
2109
|
-
| \`https://tryreplicas.com/
|
|
2120
|
+
| \`https://tryreplicas.com/organizations/<organization-id>/media/<media-id>\` | Organization-only page printed by \`--access organization\` | Pull requests and other places where every viewer belongs to the Replicas organization. |
|
|
2121
|
+
| \`https://api.tryreplicas.com/v1/media/public/<id>/<token>\` | Opt-in public bearer URL printed by \`--access public\` or \`--share\` | GitHub image embeds and intentionally public HTML page links. |
|
|
2122
|
+
| \`https://tryreplicas.com/workspaces/<workspace-id>?media=<media-id>\` | Authenticated dashboard deep link that opens the media file in the workspace | Everywhere external \u2014 Slack, GitHub, Linear, PR bodies, comments, emails. |
|
|
2110
2123
|
|
|
2111
2124
|
### NEVER link the API redirect URL outside the Replicas chat reply
|
|
2112
2125
|
|
|
@@ -2119,9 +2132,9 @@ This rule has no exceptions:
|
|
|
2119
2132
|
- \u274C Never link to it from any external doc, email, or external chat.
|
|
2120
2133
|
- \u274C Never include it as a "backup link" in case the dashboard link breaks \u2014 it will always break externally.
|
|
2121
2134
|
|
|
2122
|
-
### ALWAYS link
|
|
2135
|
+
### ALWAYS link a Replicas web URL \u2014 never the authenticated API URL \u2014 when referencing media externally
|
|
2123
2136
|
|
|
2124
|
-
|
|
2137
|
+
For an organization-only HTML page, use the \`Forge link\` printed by \`--access organization\`. For other authenticated media references, use the dashboard form:
|
|
2125
2138
|
|
|
2126
2139
|
\`\`\`
|
|
2127
2140
|
https://tryreplicas.com/workspaces/<workspace-id>?media=<media-id>
|
|
@@ -2135,7 +2148,7 @@ Always render as a markdown / mrkdwn hyperlink labeled **View in Replicas** \u20
|
|
|
2135
2148
|
|
|
2136
2149
|
## In your Replicas chat reply
|
|
2137
2150
|
|
|
2138
|
-
Include each markdown embed line **verbatim** where you want that file to render inline. The chat substitutes each one with an embedded image, video, or audio player. Multiple embeds can appear in a single reply.
|
|
2151
|
+
Include each markdown embed line **verbatim** where you want that file to render inline. The chat substitutes each one with an embedded image, video, or audio player. For HTML, use the \`HTML page\` or \`View in Replicas\` link instead. Multiple embeds can appear in a single reply.
|
|
2139
2152
|
|
|
2140
2153
|
After (or alongside) the embeds, include a \`[View in Replicas](<deep-link>)\` hyperlink for each file using the per-file dashboard URL from the CLI. This lets the user open the specific item in the workspace.
|
|
2141
2154
|
|
|
@@ -2281,6 +2294,8 @@ GitHub does not reliably render arbitrary external videos as inline players. For
|
|
|
2281
2294
|
|
|
2282
2295
|
Public forge shares are bearer capabilities. For private repositories, create one only when the user asked for inline PR media. Revoke with \`replicas media revoke <media-id>\` **only** when the user asks or the media should intentionally stop rendering \u2014 never as routine post-task cleanup, since revoking breaks every embed already posted on the PR.
|
|
2283
2296
|
|
|
2297
|
+
For a self-contained HTML report, upload it with \`--access organization\` and put the printed \`Forge link\` Markdown in the PR body or comment. GitHub cannot render the page inline, so use the normal link rather than image syntax. Use \`--access public\` only when the user explicitly wants unauthenticated access.
|
|
2298
|
+
|
|
2284
2299
|
Do **not** commit screenshots to the repo, use placeholder URLs, expose the authenticated \`/v1/media/<id>\` URL, or automate GitHub's undocumented browser upload flow.
|
|
2285
2300
|
|
|
2286
2301
|
### GitLab: native inline screenshots and videos
|
|
@@ -2315,8 +2330,9 @@ Auto-detected from the filename extension:
|
|
|
2315
2330
|
| \`png\`, \`jpg\`, \`jpeg\`, \`webp\` | image |
|
|
2316
2331
|
| \`mp4\`, \`webm\` | video |
|
|
2317
2332
|
| \`mp3\`, \`wav\` | audio |
|
|
2333
|
+
| \`html\`, \`htm\` | html |
|
|
2318
2334
|
|
|
2319
|
-
For other extensions, pass \`--kind image|video|audio\` explicitly. The kind applies to every file in that invocation, so group files of the same kind together:
|
|
2335
|
+
For other extensions, pass \`--kind image|video|audio|html\` explicitly. The kind applies to every file in that invocation, so group files of the same kind together:
|
|
2320
2336
|
|
|
2321
2337
|
\`\`\`bash
|
|
2322
2338
|
replicas media upload diagram.svg --name "Architecture diagram" --kind image
|
|
@@ -2325,15 +2341,16 @@ replicas media upload chart-a.svg chart-b.svg --name "Latency chart" --name "Err
|
|
|
2325
2341
|
|
|
2326
2342
|
## Options
|
|
2327
2343
|
|
|
2328
|
-
- \`--kind <image|video|audio>\` \u2014 override auto-detection
|
|
2344
|
+
- \`--kind <image|video|audio|html>\` \u2014 override auto-detection
|
|
2329
2345
|
- \`--name <name>\`: required display name shown in the dashboard, one per file in order
|
|
2330
2346
|
- \`--session-id <id>\` \u2014 associate the upload with a specific session
|
|
2331
|
-
- \`--
|
|
2347
|
+
- \`--access organization|public\`: create an organization-only page link or a public bearer URL
|
|
2348
|
+
- \`--share\`: alias for \`--access public\`
|
|
2332
2349
|
`;
|
|
2333
2350
|
var MEDIA_ABILITY = {
|
|
2334
2351
|
label: "Media",
|
|
2335
|
-
description: "Share screenshots, recordings, generated images, and
|
|
2336
|
-
bullet: "- Producing or showing the user any media \u2014 screenshots, screen recordings, generated images or diagrams, audio clips \u2014 including in your Replicas chat reply, PR descriptions/comments, and other external platforms",
|
|
2352
|
+
description: "Share screenshots, recordings, generated images, audio clips, and HTML pages.",
|
|
2353
|
+
bullet: "- Producing or showing the user any media \u2014 screenshots, screen recordings, generated images or diagrams, audio clips, or HTML recap pages \u2014 including in your Replicas chat reply, PR descriptions/comments, and other external platforms",
|
|
2337
2354
|
section: SECTION8,
|
|
2338
2355
|
referenceFile: { name: "MEDIA.md", content: REFERENCE8 }
|
|
2339
2356
|
};
|
|
@@ -3311,14 +3328,23 @@ function chatHistoryPageParamsFromQuery(query2) {
|
|
|
3311
3328
|
beforeTurn: parse(query2.beforeTurn)
|
|
3312
3329
|
};
|
|
3313
3330
|
}
|
|
3331
|
+
function getChatHistoryPageWindow(totalItems, limit, before) {
|
|
3332
|
+
const endIndex = Math.min(before ?? totalItems, totalItems);
|
|
3333
|
+
return { startIndex: Math.max(0, endIndex - Math.max(1, limit)), endIndex };
|
|
3334
|
+
}
|
|
3314
3335
|
function paginateChatHistory(full, params) {
|
|
3315
3336
|
if (params.limit === void 0) return { ...full, totalEvents: full.events.length };
|
|
3316
|
-
const
|
|
3317
|
-
|
|
3318
|
-
|
|
3337
|
+
const { startIndex: eventsStartIndex, endIndex: eventsEnd } = getChatHistoryPageWindow(
|
|
3338
|
+
full.events.length,
|
|
3339
|
+
params.limit,
|
|
3340
|
+
params.beforeEvent
|
|
3341
|
+
);
|
|
3319
3342
|
const turns = full.codexAspTranscript?.turns;
|
|
3320
|
-
const
|
|
3321
|
-
|
|
3343
|
+
const { startIndex: turnsStartIndex, endIndex: turnsEnd } = getChatHistoryPageWindow(
|
|
3344
|
+
turns?.length ?? 0,
|
|
3345
|
+
params.limit,
|
|
3346
|
+
params.beforeTurn
|
|
3347
|
+
);
|
|
3322
3348
|
const codexAspTranscript = full.codexAspTranscript && turns && (turnsStartIndex > 0 || turnsEnd < turns.length) ? { ...full.codexAspTranscript, turns: turns.slice(turnsStartIndex, turnsEnd) } : full.codexAspTranscript;
|
|
3323
3349
|
return {
|
|
3324
3350
|
...full,
|
|
@@ -5558,9 +5584,10 @@ var EMAIL_TEMPLATE_KEYS = [...EMAIL_KEYS, ...MANUAL_EMAIL_TEMPLATE_KEYS];
|
|
|
5558
5584
|
var MEDIA_KIND = {
|
|
5559
5585
|
IMAGE: "image",
|
|
5560
5586
|
VIDEO: "video",
|
|
5561
|
-
AUDIO: "audio"
|
|
5587
|
+
AUDIO: "audio",
|
|
5588
|
+
HTML: "html"
|
|
5562
5589
|
};
|
|
5563
|
-
var MEDIA_KINDS = [MEDIA_KIND.IMAGE, MEDIA_KIND.VIDEO, MEDIA_KIND.AUDIO];
|
|
5590
|
+
var MEDIA_KINDS = [MEDIA_KIND.IMAGE, MEDIA_KIND.VIDEO, MEDIA_KIND.AUDIO, MEDIA_KIND.HTML];
|
|
5564
5591
|
var MAX_ENGINE_LOG_BYTES = 50 * 1024 * 1024;
|
|
5565
5592
|
|
|
5566
5593
|
// ../shared/src/skill-registry.ts
|
|
@@ -9406,13 +9433,14 @@ function isNotFoundError(error) {
|
|
|
9406
9433
|
}
|
|
9407
9434
|
|
|
9408
9435
|
// src/managers/codex-asp/codex-history-file.ts
|
|
9409
|
-
import { appendFile as appendFile2, readFile as readFile9 } from "fs/promises";
|
|
9436
|
+
import { appendFile as appendFile2, open, readFile as readFile9 } from "fs/promises";
|
|
9410
9437
|
var CodexHistoryFile = class {
|
|
9411
9438
|
constructor(filePath) {
|
|
9412
9439
|
this.filePath = filePath;
|
|
9413
9440
|
}
|
|
9414
9441
|
filePath;
|
|
9415
9442
|
writeLock = new AsyncLock();
|
|
9443
|
+
eventLineIndex = null;
|
|
9416
9444
|
/** Best-effort ordered append; failures must not disrupt the turn. */
|
|
9417
9445
|
append(event) {
|
|
9418
9446
|
void this.writeLock.run(
|
|
@@ -9435,6 +9463,88 @@ var CodexHistoryFile = class {
|
|
|
9435
9463
|
return { events: [], transcript: null, transcriptsByThreadId: /* @__PURE__ */ new Map() };
|
|
9436
9464
|
}
|
|
9437
9465
|
}
|
|
9466
|
+
async loadEventsPage(page) {
|
|
9467
|
+
if (page.limit === void 0) {
|
|
9468
|
+
const history2 = await this.load();
|
|
9469
|
+
return { events: history2.events, eventsStartIndex: 0, totalEvents: history2.events.length };
|
|
9470
|
+
}
|
|
9471
|
+
let file;
|
|
9472
|
+
try {
|
|
9473
|
+
file = await open(this.filePath, "r");
|
|
9474
|
+
} catch (error) {
|
|
9475
|
+
if (!(error && typeof error === "object" && "code" in error && error.code === "ENOENT")) {
|
|
9476
|
+
console.error("[CodexHistoryFile] Failed to open history file:", error);
|
|
9477
|
+
}
|
|
9478
|
+
return { events: [], eventsStartIndex: 0, totalEvents: 0 };
|
|
9479
|
+
}
|
|
9480
|
+
try {
|
|
9481
|
+
const stats = await file.stat();
|
|
9482
|
+
let index = this.eventLineIndex;
|
|
9483
|
+
if (!index || index.size !== stats.size || index.mtimeMs !== stats.mtimeMs) {
|
|
9484
|
+
const starts = stats.size > 0 ? [0] : [];
|
|
9485
|
+
const buffer = Buffer.allocUnsafe(64 * 1024);
|
|
9486
|
+
let position = 0;
|
|
9487
|
+
while (position < stats.size) {
|
|
9488
|
+
const { bytesRead: bytesRead2 } = await file.read(
|
|
9489
|
+
buffer,
|
|
9490
|
+
0,
|
|
9491
|
+
Math.min(buffer.length, stats.size - position),
|
|
9492
|
+
position
|
|
9493
|
+
);
|
|
9494
|
+
if (bytesRead2 === 0) break;
|
|
9495
|
+
for (let offset = 0; offset < bytesRead2; offset += 1) {
|
|
9496
|
+
const next = position + offset + 1;
|
|
9497
|
+
if (buffer[offset] === 10 && next < stats.size) starts.push(next);
|
|
9498
|
+
}
|
|
9499
|
+
position += bytesRead2;
|
|
9500
|
+
}
|
|
9501
|
+
index = { size: stats.size, mtimeMs: stats.mtimeMs, starts };
|
|
9502
|
+
this.eventLineIndex = index;
|
|
9503
|
+
}
|
|
9504
|
+
const totalEvents2 = index.starts.length;
|
|
9505
|
+
const { startIndex: eventsStartIndex2, endIndex: eventsEnd2 } = getChatHistoryPageWindow(
|
|
9506
|
+
totalEvents2,
|
|
9507
|
+
page.limit,
|
|
9508
|
+
page.beforeEvent
|
|
9509
|
+
);
|
|
9510
|
+
const startByte = index.starts[eventsStartIndex2] ?? index.size;
|
|
9511
|
+
const endByte = index.starts[eventsEnd2] ?? index.size;
|
|
9512
|
+
const content = Buffer.allocUnsafe(endByte - startByte);
|
|
9513
|
+
let bytesRead = 0;
|
|
9514
|
+
while (bytesRead < content.length) {
|
|
9515
|
+
const result = await file.read(
|
|
9516
|
+
content,
|
|
9517
|
+
bytesRead,
|
|
9518
|
+
content.length - bytesRead,
|
|
9519
|
+
startByte + bytesRead
|
|
9520
|
+
);
|
|
9521
|
+
if (result.bytesRead === 0) break;
|
|
9522
|
+
bytesRead += result.bytesRead;
|
|
9523
|
+
}
|
|
9524
|
+
if (bytesRead === content.length) {
|
|
9525
|
+
const parsed = parseAgentEventJsonlWithCodexAspTranscript(content.toString("utf-8"));
|
|
9526
|
+
if (!parsed.transcript && parsed.events.length === eventsEnd2 - eventsStartIndex2) {
|
|
9527
|
+
return { events: parsed.events, eventsStartIndex: eventsStartIndex2, totalEvents: totalEvents2 };
|
|
9528
|
+
}
|
|
9529
|
+
}
|
|
9530
|
+
} catch (error) {
|
|
9531
|
+
console.error("[CodexHistoryFile] Failed to load history page:", error);
|
|
9532
|
+
} finally {
|
|
9533
|
+
await file.close();
|
|
9534
|
+
}
|
|
9535
|
+
const history = await this.load();
|
|
9536
|
+
const totalEvents = history.events.length;
|
|
9537
|
+
const { startIndex: eventsStartIndex, endIndex: eventsEnd } = getChatHistoryPageWindow(
|
|
9538
|
+
totalEvents,
|
|
9539
|
+
page.limit,
|
|
9540
|
+
page.beforeEvent
|
|
9541
|
+
);
|
|
9542
|
+
return {
|
|
9543
|
+
events: history.events.slice(eventsStartIndex, eventsEnd),
|
|
9544
|
+
eventsStartIndex,
|
|
9545
|
+
totalEvents
|
|
9546
|
+
};
|
|
9547
|
+
}
|
|
9438
9548
|
};
|
|
9439
9549
|
|
|
9440
9550
|
// src/managers/claude-activity.ts
|
|
@@ -10563,13 +10673,13 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
10563
10673
|
}
|
|
10564
10674
|
return null;
|
|
10565
10675
|
}
|
|
10566
|
-
async getHistory() {
|
|
10676
|
+
async getHistory(page = {}) {
|
|
10567
10677
|
await this.initialized;
|
|
10568
10678
|
await this.historyFile.flush();
|
|
10569
|
-
const history = await this.historyFile.
|
|
10679
|
+
const history = await this.historyFile.loadEventsPage(page);
|
|
10570
10680
|
return {
|
|
10571
10681
|
thread_id: this.sessionId,
|
|
10572
|
-
|
|
10682
|
+
...history
|
|
10573
10683
|
};
|
|
10574
10684
|
}
|
|
10575
10685
|
partialMessageStreamKey(message) {
|
|
@@ -10896,7 +11006,7 @@ var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
|
10896
11006
|
var MIN_CODEX_CLI_VERSION = "0.144.6";
|
|
10897
11007
|
var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
|
|
10898
11008
|
var codexCliVersionEnsured = null;
|
|
10899
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
11009
|
+
var ENGINE_PACKAGE_VERSION = "0.1.582";
|
|
10900
11010
|
var INITIALIZE_METHOD = "initialize";
|
|
10901
11011
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
10902
11012
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -12009,22 +12119,24 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
12009
12119
|
this.recordUserMessageEvent(request);
|
|
12010
12120
|
return true;
|
|
12011
12121
|
}
|
|
12012
|
-
async getHistory() {
|
|
12122
|
+
async getHistory(page = {}) {
|
|
12013
12123
|
if (!this.currentThreadId) {
|
|
12014
|
-
return { thread_id: null, events: [], goal: null };
|
|
12124
|
+
return paginateChatHistory({ thread_id: null, events: [], goal: null }, page);
|
|
12015
12125
|
}
|
|
12016
|
-
if (this.
|
|
12017
|
-
|
|
12018
|
-
|
|
12019
|
-
|
|
12020
|
-
|
|
12126
|
+
if (this.codexAspTranscript?.threadId === this.currentThreadId) {
|
|
12127
|
+
if (page.beforeEvent === void 0 && page.beforeTurn === void 0) {
|
|
12128
|
+
try {
|
|
12129
|
+
const host = await getCodexAspHost();
|
|
12130
|
+
await this.refreshThreadGoal(host, this.currentThreadId);
|
|
12131
|
+
} catch {
|
|
12132
|
+
}
|
|
12021
12133
|
}
|
|
12022
|
-
return {
|
|
12134
|
+
return paginateChatHistory({
|
|
12023
12135
|
thread_id: this.currentThreadId,
|
|
12024
12136
|
events: [...this.historyEvents],
|
|
12025
12137
|
codexAspTranscript: this.codexAspTranscript,
|
|
12026
12138
|
goal: this.currentGoal
|
|
12027
|
-
};
|
|
12139
|
+
}, page);
|
|
12028
12140
|
}
|
|
12029
12141
|
try {
|
|
12030
12142
|
const host = await getCodexAspHost();
|
|
@@ -12039,20 +12151,20 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
12039
12151
|
if (transcript) {
|
|
12040
12152
|
transcript.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
12041
12153
|
}
|
|
12042
|
-
return {
|
|
12154
|
+
return paginateChatHistory({
|
|
12043
12155
|
thread_id: this.currentThreadId,
|
|
12044
12156
|
events: [...this.historyEvents],
|
|
12045
12157
|
codexAspTranscript: transcript,
|
|
12046
12158
|
goal: this.currentGoal
|
|
12047
|
-
};
|
|
12159
|
+
}, page);
|
|
12048
12160
|
} catch {
|
|
12049
12161
|
}
|
|
12050
|
-
return {
|
|
12162
|
+
return paginateChatHistory({
|
|
12051
12163
|
thread_id: this.currentThreadId,
|
|
12052
12164
|
events: [...this.historyEvents],
|
|
12053
12165
|
codexAspTranscript: this.codexAspTranscript,
|
|
12054
12166
|
goal: this.currentGoal
|
|
12055
|
-
};
|
|
12167
|
+
}, page);
|
|
12056
12168
|
}
|
|
12057
12169
|
getGoal() {
|
|
12058
12170
|
return this.currentGoal;
|
|
@@ -13260,12 +13372,12 @@ var CursorManager = class extends CodingAgentManager {
|
|
|
13260
13372
|
}
|
|
13261
13373
|
this.agent = null;
|
|
13262
13374
|
}
|
|
13263
|
-
async getHistory() {
|
|
13375
|
+
async getHistory(page = {}) {
|
|
13264
13376
|
await this.historyFile.flush();
|
|
13265
|
-
const history = await this.historyFile.
|
|
13377
|
+
const history = await this.historyFile.loadEventsPage(page);
|
|
13266
13378
|
return {
|
|
13267
13379
|
thread_id: this.agent?.agentId ?? this.initialSessionId,
|
|
13268
|
-
|
|
13380
|
+
...history,
|
|
13269
13381
|
goal: null
|
|
13270
13382
|
};
|
|
13271
13383
|
}
|
|
@@ -13859,12 +13971,12 @@ var OpencodeManager = class extends CodingAgentManager {
|
|
|
13859
13971
|
{ throwOnError: true }
|
|
13860
13972
|
);
|
|
13861
13973
|
}
|
|
13862
|
-
async getHistory() {
|
|
13974
|
+
async getHistory(page = {}) {
|
|
13863
13975
|
await this.historyFile.flush();
|
|
13864
|
-
const history = await this.historyFile.
|
|
13976
|
+
const history = await this.historyFile.loadEventsPage(page);
|
|
13865
13977
|
return {
|
|
13866
13978
|
thread_id: this.sessionId ?? this.initialSessionId,
|
|
13867
|
-
|
|
13979
|
+
...history,
|
|
13868
13980
|
goal: null
|
|
13869
13981
|
};
|
|
13870
13982
|
}
|
|
@@ -14435,10 +14547,10 @@ var PiManager = class extends CodingAgentManager {
|
|
|
14435
14547
|
this.recordUserMessage(session, request.message);
|
|
14436
14548
|
return true;
|
|
14437
14549
|
}
|
|
14438
|
-
async getHistory() {
|
|
14550
|
+
async getHistory(page = {}) {
|
|
14439
14551
|
await this.historyFile.flush();
|
|
14440
|
-
const history = await this.historyFile.
|
|
14441
|
-
return { thread_id: this.activeSessionFile ?? this.initialSessionId,
|
|
14552
|
+
const history = await this.historyFile.loadEventsPage(page);
|
|
14553
|
+
return { thread_id: this.activeSessionFile ?? this.initialSessionId, ...history, goal: null };
|
|
14442
14554
|
}
|
|
14443
14555
|
async listSlashCommands() {
|
|
14444
14556
|
await this.initialized;
|
|
@@ -15155,8 +15267,8 @@ var RelayManager = class {
|
|
|
15155
15267
|
async interrupt() {
|
|
15156
15268
|
return this.inner.interrupt();
|
|
15157
15269
|
}
|
|
15158
|
-
async getHistory() {
|
|
15159
|
-
return this.inner.getHistory();
|
|
15270
|
+
async getHistory(page = {}) {
|
|
15271
|
+
return this.inner.getHistory(page);
|
|
15160
15272
|
}
|
|
15161
15273
|
async listSlashCommands() {
|
|
15162
15274
|
return this.inner.listSlashCommands?.() ?? [];
|
|
@@ -16419,17 +16531,27 @@ var ChatService = class {
|
|
|
16419
16531
|
async getChatHistory(chatId, page = {}) {
|
|
16420
16532
|
const chat = this.requireChat(chatId);
|
|
16421
16533
|
const [history, senders] = await Promise.all([
|
|
16422
|
-
chat.provider.getHistory(),
|
|
16534
|
+
chat.provider.getHistory(page),
|
|
16423
16535
|
this.readSenders(chatId)
|
|
16424
16536
|
]);
|
|
16425
16537
|
for (const [messageId, acceptedEvent] of chat.acceptedUserEvents) {
|
|
16426
|
-
if (acceptedEventInCodexTranscript(acceptedEvent, history.codexAspTranscript)) {
|
|
16538
|
+
if (acceptedEventInCodexTranscript(acceptedEvent, history.codexAspTranscript) || history.events.some((event) => isSameAcceptedUserEvent(event, acceptedEvent))) {
|
|
16427
16539
|
chat.acceptedUserEvents.delete(messageId);
|
|
16428
16540
|
}
|
|
16429
16541
|
}
|
|
16542
|
+
const isLatestPage = page.beforeEvent === void 0 && page.beforeTurn === void 0;
|
|
16430
16543
|
const queuedMessageIds = new Set(chat.provider.getQueue().map((message) => message.id));
|
|
16431
|
-
const acceptedEvents = [...chat.acceptedUserEvents.entries()].filter(([messageId]) => messageId === chat.activeMessageId || !chat.hasActiveTurn && chat.pendingMessageIds[0] === messageId && !queuedMessageIds.has(messageId)).map(([, acceptedEvent]) => acceptedEvent).filter((acceptedEvent) => !acceptedEventInCodexTranscript(acceptedEvent, history.codexAspTranscript) && !history.events.some((event) => isSameAcceptedUserEvent(event, acceptedEvent)));
|
|
16544
|
+
const acceptedEvents = (isLatestPage ? [...chat.acceptedUserEvents.entries()] : []).filter(([messageId]) => messageId === chat.activeMessageId || !chat.hasActiveTurn && chat.pendingMessageIds[0] === messageId && !queuedMessageIds.has(messageId)).map(([, acceptedEvent]) => acceptedEvent).filter((acceptedEvent) => !acceptedEventInCodexTranscript(acceptedEvent, history.codexAspTranscript) && !history.events.some((event) => isSameAcceptedUserEvent(event, acceptedEvent)));
|
|
16432
16545
|
const events = [...history.events, ...acceptedEvents].sort((a, b) => getEventTimestampMs(a) - getEventTimestampMs(b));
|
|
16546
|
+
if (history.eventsStartIndex !== void 0) {
|
|
16547
|
+
return {
|
|
16548
|
+
...history,
|
|
16549
|
+
events,
|
|
16550
|
+
totalEvents: (history.totalEvents ?? history.eventsStartIndex + history.events.length) + acceptedEvents.length,
|
|
16551
|
+
goal: history.goal ?? chat.provider.getGoal?.() ?? null,
|
|
16552
|
+
senders
|
|
16553
|
+
};
|
|
16554
|
+
}
|
|
16433
16555
|
return paginateChatHistory({
|
|
16434
16556
|
thread_id: history.thread_id,
|
|
16435
16557
|
events,
|