@vibedeckx/linux-x64 0.3.23 → 0.3.25
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/bin.js +451 -278
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -4594,7 +4594,7 @@ var require_W3CTraceContextPropagator = __commonJS({
|
|
|
4594
4594
|
var TraceState_1 = require_TraceState();
|
|
4595
4595
|
exports.TRACE_PARENT_HEADER = "traceparent";
|
|
4596
4596
|
exports.TRACE_STATE_HEADER = "tracestate";
|
|
4597
|
-
var
|
|
4597
|
+
var VERSION9 = "00";
|
|
4598
4598
|
var VERSION_PART = "(?!ff)[\\da-f]{2}";
|
|
4599
4599
|
var TRACE_ID_PART = "(?![0]{32})[\\da-f]{32}";
|
|
4600
4600
|
var PARENT_ID_PART = "(?![0]{16})[\\da-f]{16}";
|
|
@@ -4618,7 +4618,7 @@ var require_W3CTraceContextPropagator = __commonJS({
|
|
|
4618
4618
|
const spanContext = api_1.trace.getSpanContext(context2);
|
|
4619
4619
|
if (!spanContext || (0, suppress_tracing_1.isTracingSuppressed)(context2) || !(0, api_1.isSpanContextValid)(spanContext))
|
|
4620
4620
|
return;
|
|
4621
|
-
const traceParent = `${
|
|
4621
|
+
const traceParent = `${VERSION9}-${spanContext.traceId}-${spanContext.spanId}-0${Number(spanContext.traceFlags || api_1.TraceFlags.NONE).toString(16)}`;
|
|
4622
4622
|
setter.set(carrier, exports.TRACE_PARENT_HEADER, traceParent);
|
|
4623
4623
|
if (spanContext.traceState) {
|
|
4624
4624
|
setter.set(carrier, exports.TRACE_STATE_HEADER, spanContext.traceState.serialize());
|
|
@@ -9571,32 +9571,32 @@ var require_Meter = __commonJS({
|
|
|
9571
9571
|
*/
|
|
9572
9572
|
createGauge(name25, options) {
|
|
9573
9573
|
const descriptor = (0, InstrumentDescriptor_1.createInstrumentDescriptor)(name25, MetricData_1.InstrumentType.GAUGE, options);
|
|
9574
|
-
const
|
|
9575
|
-
return new Instruments_1.GaugeInstrument(
|
|
9574
|
+
const storage2 = this._meterSharedState.registerMetricStorage(descriptor);
|
|
9575
|
+
return new Instruments_1.GaugeInstrument(storage2, descriptor);
|
|
9576
9576
|
}
|
|
9577
9577
|
/**
|
|
9578
9578
|
* Create a {@link Histogram} instrument.
|
|
9579
9579
|
*/
|
|
9580
9580
|
createHistogram(name25, options) {
|
|
9581
9581
|
const descriptor = (0, InstrumentDescriptor_1.createInstrumentDescriptor)(name25, MetricData_1.InstrumentType.HISTOGRAM, options);
|
|
9582
|
-
const
|
|
9583
|
-
return new Instruments_1.HistogramInstrument(
|
|
9582
|
+
const storage2 = this._meterSharedState.registerMetricStorage(descriptor);
|
|
9583
|
+
return new Instruments_1.HistogramInstrument(storage2, descriptor);
|
|
9584
9584
|
}
|
|
9585
9585
|
/**
|
|
9586
9586
|
* Create a {@link Counter} instrument.
|
|
9587
9587
|
*/
|
|
9588
9588
|
createCounter(name25, options) {
|
|
9589
9589
|
const descriptor = (0, InstrumentDescriptor_1.createInstrumentDescriptor)(name25, MetricData_1.InstrumentType.COUNTER, options);
|
|
9590
|
-
const
|
|
9591
|
-
return new Instruments_1.CounterInstrument(
|
|
9590
|
+
const storage2 = this._meterSharedState.registerMetricStorage(descriptor);
|
|
9591
|
+
return new Instruments_1.CounterInstrument(storage2, descriptor);
|
|
9592
9592
|
}
|
|
9593
9593
|
/**
|
|
9594
9594
|
* Create a {@link UpDownCounter} instrument.
|
|
9595
9595
|
*/
|
|
9596
9596
|
createUpDownCounter(name25, options) {
|
|
9597
9597
|
const descriptor = (0, InstrumentDescriptor_1.createInstrumentDescriptor)(name25, MetricData_1.InstrumentType.UP_DOWN_COUNTER, options);
|
|
9598
|
-
const
|
|
9599
|
-
return new Instruments_1.UpDownCounterInstrument(
|
|
9598
|
+
const storage2 = this._meterSharedState.registerMetricStorage(descriptor);
|
|
9599
|
+
return new Instruments_1.UpDownCounterInstrument(storage2, descriptor);
|
|
9600
9600
|
}
|
|
9601
9601
|
/**
|
|
9602
9602
|
* Create a {@link ObservableGauge} instrument.
|
|
@@ -10084,16 +10084,16 @@ var require_MetricStorageRegistry = __commonJS({
|
|
|
10084
10084
|
}
|
|
10085
10085
|
return storages;
|
|
10086
10086
|
}
|
|
10087
|
-
register(
|
|
10088
|
-
this._registerStorage(
|
|
10087
|
+
register(storage2) {
|
|
10088
|
+
this._registerStorage(storage2, this._sharedRegistry);
|
|
10089
10089
|
}
|
|
10090
|
-
registerForCollector(collector,
|
|
10090
|
+
registerForCollector(collector, storage2) {
|
|
10091
10091
|
let storageMap = this._perCollectorRegistry.get(collector);
|
|
10092
10092
|
if (storageMap == null) {
|
|
10093
10093
|
storageMap = /* @__PURE__ */ new Map();
|
|
10094
10094
|
this._perCollectorRegistry.set(collector, storageMap);
|
|
10095
10095
|
}
|
|
10096
|
-
this._registerStorage(
|
|
10096
|
+
this._registerStorage(storage2, storageMap);
|
|
10097
10097
|
}
|
|
10098
10098
|
findOrUpdateCompatibleStorage(expectedDescriptor) {
|
|
10099
10099
|
const storages = this._sharedRegistry.get(expectedDescriptor.name);
|
|
@@ -10113,14 +10113,14 @@ var require_MetricStorageRegistry = __commonJS({
|
|
|
10113
10113
|
}
|
|
10114
10114
|
return this._findOrUpdateCompatibleStorage(expectedDescriptor, storages);
|
|
10115
10115
|
}
|
|
10116
|
-
_registerStorage(
|
|
10117
|
-
const descriptor =
|
|
10116
|
+
_registerStorage(storage2, storageMap) {
|
|
10117
|
+
const descriptor = storage2.getInstrumentDescriptor();
|
|
10118
10118
|
const storages = storageMap.get(descriptor.name);
|
|
10119
10119
|
if (storages === void 0) {
|
|
10120
|
-
storageMap.set(descriptor.name, [
|
|
10120
|
+
storageMap.set(descriptor.name, [storage2]);
|
|
10121
10121
|
return;
|
|
10122
10122
|
}
|
|
10123
|
-
storages.push(
|
|
10123
|
+
storages.push(storage2);
|
|
10124
10124
|
}
|
|
10125
10125
|
_findOrUpdateCompatibleStorage(expectedDescriptor, existingStorages) {
|
|
10126
10126
|
let compatibleStorage = null;
|
|
@@ -10550,9 +10550,9 @@ var require_MeterSharedState = __commonJS({
|
|
|
10550
10550
|
}
|
|
10551
10551
|
const aggregator = aggregation.createAggregator(descriptor);
|
|
10552
10552
|
const cardinalityLimit = collector.selectCardinalityLimit(descriptor.type);
|
|
10553
|
-
const
|
|
10554
|
-
this.metricStorageRegistry.registerForCollector(collector,
|
|
10555
|
-
return
|
|
10553
|
+
const storage2 = new MetricStorageType(descriptor, aggregator, (0, AttributesProcessor_1.createNoopAttributesProcessor)(), [collector], cardinalityLimit);
|
|
10554
|
+
this.metricStorageRegistry.registerForCollector(collector, storage2);
|
|
10555
|
+
return storage2;
|
|
10556
10556
|
});
|
|
10557
10557
|
storages = storages.concat(collectorStorages);
|
|
10558
10558
|
}
|
|
@@ -95415,7 +95415,7 @@ var require_light_my_request = __commonJS({
|
|
|
95415
95415
|
var require_fastify = __commonJS({
|
|
95416
95416
|
"../../node_modules/.pnpm/fastify@5.7.2/node_modules/fastify/fastify.js"(exports, module) {
|
|
95417
95417
|
"use strict";
|
|
95418
|
-
var
|
|
95418
|
+
var VERSION9 = "5.7.2";
|
|
95419
95419
|
var Avvio = require_boot();
|
|
95420
95420
|
var http = __require("node:http");
|
|
95421
95421
|
var diagnostics = __require("node:diagnostics_channel");
|
|
@@ -95716,7 +95716,7 @@ var require_fastify = __commonJS({
|
|
|
95716
95716
|
version: {
|
|
95717
95717
|
configurable: true,
|
|
95718
95718
|
get() {
|
|
95719
|
-
return
|
|
95719
|
+
return VERSION9;
|
|
95720
95720
|
}
|
|
95721
95721
|
},
|
|
95722
95722
|
errorHandler: {
|
|
@@ -107959,7 +107959,7 @@ var require_websocket = __commonJS({
|
|
|
107959
107959
|
var http = __require("http");
|
|
107960
107960
|
var net2 = __require("net");
|
|
107961
107961
|
var tls = __require("tls");
|
|
107962
|
-
var { randomBytes:
|
|
107962
|
+
var { randomBytes: randomBytes5, createHash: createHash9 } = __require("crypto");
|
|
107963
107963
|
var { Duplex, Readable: Readable4 } = __require("stream");
|
|
107964
107964
|
var { URL: URL2 } = __require("url");
|
|
107965
107965
|
var PerMessageDeflate = require_permessage_deflate();
|
|
@@ -108489,7 +108489,7 @@ var require_websocket = __commonJS({
|
|
|
108489
108489
|
}
|
|
108490
108490
|
}
|
|
108491
108491
|
const defaultPort = isSecure ? 443 : 80;
|
|
108492
|
-
const key2 =
|
|
108492
|
+
const key2 = randomBytes5(16).toString("base64");
|
|
108493
108493
|
const request = isSecure ? https.request : http.request;
|
|
108494
108494
|
const protocolSet = /* @__PURE__ */ new Set();
|
|
108495
108495
|
let perMessageDeflate;
|
|
@@ -112389,7 +112389,7 @@ var require_websocket2 = __commonJS({
|
|
|
112389
112389
|
"use strict";
|
|
112390
112390
|
var { ServerResponse } = __require("node:http");
|
|
112391
112391
|
var { PassThrough } = __require("node:stream");
|
|
112392
|
-
var { randomBytes:
|
|
112392
|
+
var { randomBytes: randomBytes5 } = __require("node:crypto");
|
|
112393
112393
|
var fp36 = require_plugin2();
|
|
112394
112394
|
var WebSocket2 = require_ws();
|
|
112395
112395
|
var Duplexify = require_duplexify();
|
|
@@ -112460,7 +112460,7 @@ var require_websocket2 = __commonJS({
|
|
|
112460
112460
|
connection: "upgrade",
|
|
112461
112461
|
upgrade: "websocket",
|
|
112462
112462
|
"sec-websocket-version": 13,
|
|
112463
|
-
"sec-websocket-key":
|
|
112463
|
+
"sec-websocket-key": randomBytes5(16).toString("base64")
|
|
112464
112464
|
},
|
|
112465
112465
|
httpVersion: "1.1",
|
|
112466
112466
|
url: path23,
|
|
@@ -132602,7 +132602,7 @@ var require_sqlite_cache_store = __commonJS({
|
|
|
132602
132602
|
var { Writable: Writable2 } = __require("node:stream");
|
|
132603
132603
|
var { assertCacheKey, assertCacheValue } = require_cache();
|
|
132604
132604
|
var DatabaseSync;
|
|
132605
|
-
var
|
|
132605
|
+
var VERSION9 = 3;
|
|
132606
132606
|
var MAX_ENTRY_SIZE = 2 * 1e3 * 1e3 * 1e3;
|
|
132607
132607
|
module.exports = class SqliteCacheStore {
|
|
132608
132608
|
#maxEntrySize = MAX_ENTRY_SIZE;
|
|
@@ -132673,7 +132673,7 @@ var require_sqlite_cache_store = __commonJS({
|
|
|
132673
132673
|
PRAGMA temp_store = memory;
|
|
132674
132674
|
PRAGMA optimize;
|
|
132675
132675
|
|
|
132676
|
-
CREATE TABLE IF NOT EXISTS cacheInterceptorV${
|
|
132676
|
+
CREATE TABLE IF NOT EXISTS cacheInterceptorV${VERSION9} (
|
|
132677
132677
|
-- Data specific to us
|
|
132678
132678
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
132679
132679
|
url TEXT NOT NULL,
|
|
@@ -132692,8 +132692,8 @@ var require_sqlite_cache_store = __commonJS({
|
|
|
132692
132692
|
staleAt INTEGER NOT NULL
|
|
132693
132693
|
);
|
|
132694
132694
|
|
|
132695
|
-
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${
|
|
132696
|
-
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${
|
|
132695
|
+
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION9}_getValuesQuery ON cacheInterceptorV${VERSION9}(url, method, deleteAt);
|
|
132696
|
+
CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION9}_deleteByUrlQuery ON cacheInterceptorV${VERSION9}(deleteAt);
|
|
132697
132697
|
`);
|
|
132698
132698
|
this.#getValuesQuery = this.#db.prepare(`
|
|
132699
132699
|
SELECT
|
|
@@ -132708,7 +132708,7 @@ var require_sqlite_cache_store = __commonJS({
|
|
|
132708
132708
|
vary,
|
|
132709
132709
|
cachedAt,
|
|
132710
132710
|
staleAt
|
|
132711
|
-
FROM cacheInterceptorV${
|
|
132711
|
+
FROM cacheInterceptorV${VERSION9}
|
|
132712
132712
|
WHERE
|
|
132713
132713
|
url = ?
|
|
132714
132714
|
AND method = ?
|
|
@@ -132716,7 +132716,7 @@ var require_sqlite_cache_store = __commonJS({
|
|
|
132716
132716
|
deleteAt ASC
|
|
132717
132717
|
`);
|
|
132718
132718
|
this.#updateValueQuery = this.#db.prepare(`
|
|
132719
|
-
UPDATE cacheInterceptorV${
|
|
132719
|
+
UPDATE cacheInterceptorV${VERSION9} SET
|
|
132720
132720
|
body = ?,
|
|
132721
132721
|
deleteAt = ?,
|
|
132722
132722
|
statusCode = ?,
|
|
@@ -132730,7 +132730,7 @@ var require_sqlite_cache_store = __commonJS({
|
|
|
132730
132730
|
id = ?
|
|
132731
132731
|
`);
|
|
132732
132732
|
this.#insertValueQuery = this.#db.prepare(`
|
|
132733
|
-
INSERT INTO cacheInterceptorV${
|
|
132733
|
+
INSERT INTO cacheInterceptorV${VERSION9} (
|
|
132734
132734
|
url,
|
|
132735
132735
|
method,
|
|
132736
132736
|
body,
|
|
@@ -132746,20 +132746,20 @@ var require_sqlite_cache_store = __commonJS({
|
|
|
132746
132746
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
132747
132747
|
`);
|
|
132748
132748
|
this.#deleteByUrlQuery = this.#db.prepare(
|
|
132749
|
-
`DELETE FROM cacheInterceptorV${
|
|
132749
|
+
`DELETE FROM cacheInterceptorV${VERSION9} WHERE url = ?`
|
|
132750
132750
|
);
|
|
132751
132751
|
this.#countEntriesQuery = this.#db.prepare(
|
|
132752
|
-
`SELECT COUNT(*) AS total FROM cacheInterceptorV${
|
|
132752
|
+
`SELECT COUNT(*) AS total FROM cacheInterceptorV${VERSION9}`
|
|
132753
132753
|
);
|
|
132754
132754
|
this.#deleteExpiredValuesQuery = this.#db.prepare(
|
|
132755
|
-
`DELETE FROM cacheInterceptorV${
|
|
132755
|
+
`DELETE FROM cacheInterceptorV${VERSION9} WHERE deleteAt <= ?`
|
|
132756
132756
|
);
|
|
132757
132757
|
this.#deleteOldValuesQuery = this.#maxCount === Infinity ? null : this.#db.prepare(`
|
|
132758
|
-
DELETE FROM cacheInterceptorV${
|
|
132758
|
+
DELETE FROM cacheInterceptorV${VERSION9}
|
|
132759
132759
|
WHERE id IN (
|
|
132760
132760
|
SELECT
|
|
132761
132761
|
id
|
|
132762
|
-
FROM cacheInterceptorV${
|
|
132762
|
+
FROM cacheInterceptorV${VERSION9}
|
|
132763
132763
|
ORDER BY cachedAt DESC
|
|
132764
132764
|
LIMIT ?
|
|
132765
132765
|
)
|
|
@@ -136302,8 +136302,8 @@ var require_cache3 = __commonJS({
|
|
|
136302
136302
|
*/
|
|
136303
136303
|
#queryCache(requestQuery, options, targetStorage) {
|
|
136304
136304
|
const resultList = [];
|
|
136305
|
-
const
|
|
136306
|
-
for (const requestResponse of
|
|
136305
|
+
const storage2 = targetStorage ?? this.#relevantRequestResponseList;
|
|
136306
|
+
for (const requestResponse of storage2) {
|
|
136307
136307
|
const [cachedRequest, cachedResponse] = requestResponse;
|
|
136308
136308
|
if (this.#requestMatchesCachedItem(requestQuery, cachedRequest, cachedResponse, options)) {
|
|
136309
136309
|
resultList.push(requestResponse);
|
|
@@ -205475,8 +205475,8 @@ function verifySessionToolsToken(secret, token, nowMs) {
|
|
|
205475
205475
|
if (typeof wire.exp !== "number" || nowMs >= wire.exp) return null;
|
|
205476
205476
|
return { sessionId: wire.s };
|
|
205477
205477
|
}
|
|
205478
|
-
async function getSessionToolsSecret(
|
|
205479
|
-
return
|
|
205478
|
+
async function getSessionToolsSecret(storage2) {
|
|
205479
|
+
return storage2.settings.getOrCreate(
|
|
205480
205480
|
SESSION_TOOLS_SECRET_SETTING,
|
|
205481
205481
|
() => randomBytes(32).toString("hex")
|
|
205482
205482
|
);
|
|
@@ -205488,9 +205488,18 @@ var SESSION_TOOLS_MCP_SERVER_NAME = "vibedeckx";
|
|
|
205488
205488
|
var PROPOSE_SCHEDULE_TOOL = "propose_schedule";
|
|
205489
205489
|
var CANONICAL_PROPOSE_SCHEDULE_TOOL = `mcp__${SESSION_TOOLS_MCP_SERVER_NAME}__${PROPOSE_SCHEDULE_TOOL}`;
|
|
205490
205490
|
var PROPOSE_SCHEDULE_DESCRIPTION = [
|
|
205491
|
-
"Propose a recurring scheduled check to the user.
|
|
205492
|
-
"
|
|
205493
|
-
|
|
205491
|
+
"Propose a recurring scheduled check to the user. This is the only way to schedule work in this",
|
|
205492
|
+
"environment. Call it in either situation:",
|
|
205493
|
+
'- The user asks for something recurring \u2014 "every morning", "nightly", "hourly", "on a cron",',
|
|
205494
|
+
' "keep an eye on". Such a request IS this tool; it is not a programming task.',
|
|
205495
|
+
"- You are telling the user that something needs periodic follow-up observation \u2014 e.g. after a",
|
|
205496
|
+
" fix whose effect can only be confirmed over time, or a flaky failure worth watching.",
|
|
205497
|
+
"",
|
|
205498
|
+
"Never satisfy a scheduling request by writing a crontab entry, systemd timer, launchd plist, CI",
|
|
205499
|
+
"cron trigger, setInterval, or sleep loop: the platform owns execution, and anything you wire up",
|
|
205500
|
+
"by hand is invisible to the user and does not survive this session. (Adding scheduling to the",
|
|
205501
|
+
"user's OWN product \u2014 a cron block in their deployment config, a timer in their app \u2014 is still",
|
|
205502
|
+
"ordinary coding work. This tool is for scheduling YOUR follow-up runs, not their features.)",
|
|
205494
205503
|
"",
|
|
205495
205504
|
"The proposal is shown to the user as a confirmation card; it does NOT create anything by",
|
|
205496
205505
|
"itself and this call does not wait for the user. Say you have SUGGESTED a scheduled check",
|
|
@@ -205510,6 +205519,18 @@ var PROPOSE_SCHEDULE_DESCRIPTION = [
|
|
|
205510
205519
|
"",
|
|
205511
205520
|
"Project, execution target and branch are taken from this session \u2014 do not describe them here."
|
|
205512
205521
|
].join("\n");
|
|
205522
|
+
var SESSION_TOOLS_MCP_INSTRUCTIONS = [
|
|
205523
|
+
`\`${PROPOSE_SCHEDULE_TOOL}\` is the only way to schedule work in this environment.`,
|
|
205524
|
+
'When the user asks for anything recurring \u2014 nightly, hourly, every morning, on a cron, "keep',
|
|
205525
|
+
'watching" \u2014 call it instead of writing a crontab entry, systemd timer, or setInterval loop.',
|
|
205526
|
+
"Scheduling inside the user's own product remains ordinary coding work."
|
|
205527
|
+
].join("\n");
|
|
205528
|
+
var SESSION_TOOLS_SYSTEM_PROMPT_HINT = [
|
|
205529
|
+
"Scheduling: when the user asks you to run something on a schedule (nightly, hourly, every",
|
|
205530
|
+
`morning, on a cron, "keep watching"), call the \`${CANONICAL_PROPOSE_SCHEDULE_TOOL}\` tool. That`,
|
|
205531
|
+
"is the only way to schedule work here \u2014 do not hand-roll a crontab entry, systemd timer, or",
|
|
205532
|
+
"setInterval loop for it. Writing scheduling into the user's own project is still normal coding."
|
|
205533
|
+
].join(" ");
|
|
205513
205534
|
var PROPOSE_SCHEDULE_INPUT_SCHEMA = {
|
|
205514
205535
|
type: "object",
|
|
205515
205536
|
properties: {
|
|
@@ -205849,7 +205870,7 @@ function withNpxFallback(nativeBinary, args) {
|
|
|
205849
205870
|
}
|
|
205850
205871
|
return { command: "npx", args: ["-y", CLAUDE_NPM_PACKAGE, ...args] };
|
|
205851
205872
|
}
|
|
205852
|
-
function buildClaudeSessionSpawnConfig(nativeBinary, permissionMode, mcpConfigArg, model, allowedTools) {
|
|
205873
|
+
function buildClaudeSessionSpawnConfig(nativeBinary, permissionMode, mcpConfigArg, model, allowedTools, appendSystemPrompt) {
|
|
205853
205874
|
const permissionFlag = permissionMode === "plan" ? "--permission-mode=plan" : "--dangerously-skip-permissions";
|
|
205854
205875
|
const args = [
|
|
205855
205876
|
...STREAM_JSON_ARGS,
|
|
@@ -205873,6 +205894,9 @@ function buildClaudeSessionSpawnConfig(nativeBinary, permissionMode, mcpConfigAr
|
|
|
205873
205894
|
if (allowedTools?.length) {
|
|
205874
205895
|
args.push("--allowedTools", allowedTools.join(","));
|
|
205875
205896
|
}
|
|
205897
|
+
if (appendSystemPrompt?.trim()) {
|
|
205898
|
+
args.push("--append-system-prompt", appendSystemPrompt.trim());
|
|
205899
|
+
}
|
|
205876
205900
|
return withNpxFallback(nativeBinary, args);
|
|
205877
205901
|
}
|
|
205878
205902
|
function buildClaudeStreamExecutorSpawn(nativeBinary) {
|
|
@@ -205940,8 +205964,8 @@ var ProcessManager = class _ProcessManager {
|
|
|
205940
205964
|
storage;
|
|
205941
205965
|
eventBus = null;
|
|
205942
205966
|
terminalCounter = 0;
|
|
205943
|
-
constructor(
|
|
205944
|
-
this.storage =
|
|
205967
|
+
constructor(storage2) {
|
|
205968
|
+
this.storage = storage2;
|
|
205945
205969
|
}
|
|
205946
205970
|
/** Payload size of one entry; `finished` carries an uncapped finalResult. */
|
|
205947
205971
|
static logMessageBytes(msg) {
|
|
@@ -207084,7 +207108,8 @@ var ClaudeCodeProvider = class {
|
|
|
207084
207108
|
permissionMode,
|
|
207085
207109
|
Object.keys(mcpServers).length > 0 ? buildClaudeMcpConfigArg(mcpServers) : void 0,
|
|
207086
207110
|
model,
|
|
207087
|
-
sessionToolsMcp ? [CANONICAL_PROPOSE_SCHEDULE_TOOL] : void 0
|
|
207111
|
+
sessionToolsMcp ? [CANONICAL_PROPOSE_SCHEDULE_TOOL] : void 0,
|
|
207112
|
+
sessionToolsMcp ? SESSION_TOOLS_SYSTEM_PROMPT_HINT : void 0
|
|
207088
207113
|
);
|
|
207089
207114
|
}
|
|
207090
207115
|
parseStdoutLine(line, _sessionId) {
|
|
@@ -207966,22 +207991,22 @@ function reconcileWorktreeBranches(projectPath, entries, sessionBranches = [], r
|
|
|
207966
207991
|
}
|
|
207967
207992
|
return worktrees;
|
|
207968
207993
|
}
|
|
207969
|
-
async function getRegisteredWorktreeBranches(
|
|
207994
|
+
async function getRegisteredWorktreeBranches(storage2, projectId, projectPath) {
|
|
207970
207995
|
const entries = readWorktreeListTolerant(projectPath);
|
|
207971
|
-
const sessions = await
|
|
207996
|
+
const sessions = await storage2.agentSessions.getProjectedByProjectId(projectId, "runtime");
|
|
207972
207997
|
const sessionBranches = sessions.map((session) => session.branch);
|
|
207973
207998
|
const sessionBranchByPath = /* @__PURE__ */ new Map();
|
|
207974
207999
|
for (const branch of sessionBranches) {
|
|
207975
208000
|
if (branch) sessionBranchByPath.set(path7.resolve(conventionalWorktreePath(projectPath, branch)), branch);
|
|
207976
208001
|
}
|
|
207977
|
-
let registered = await
|
|
208002
|
+
let registered = await storage2.workspaceRegistry.listByProject(projectId, "local");
|
|
207978
208003
|
const livePaths = new Set(entries.map((entry) => path7.resolve(entry.path)));
|
|
207979
208004
|
for (const row of registered) {
|
|
207980
208005
|
if (livePaths.has(path7.resolve(row.checkout.worktree_path))) continue;
|
|
207981
208006
|
if (row.checkout.status === "deleting") {
|
|
207982
|
-
await
|
|
208007
|
+
await storage2.workspaceRegistry.markCheckoutDeleted(row.checkout.id);
|
|
207983
208008
|
} else if (row.checkout.status !== "error" || row.checkout.error !== "Worktree is missing") {
|
|
207984
|
-
await
|
|
208009
|
+
await storage2.workspaceRegistry.setCheckoutStatusIfCurrent(
|
|
207985
208010
|
row.checkout.id,
|
|
207986
208011
|
{ status: row.checkout.status, updatedAt: row.checkout.updated_at },
|
|
207987
208012
|
"error",
|
|
@@ -207989,7 +208014,7 @@ async function getRegisteredWorktreeBranches(storage, projectId, projectPath) {
|
|
|
207989
208014
|
);
|
|
207990
208015
|
}
|
|
207991
208016
|
}
|
|
207992
|
-
registered = await
|
|
208017
|
+
registered = await storage2.workspaceRegistry.listByProject(projectId, "local");
|
|
207993
208018
|
const registeredPaths = new Set(registered.map((row) => path7.resolve(row.checkout.worktree_path)));
|
|
207994
208019
|
for (let index = 0; index < entries.length; index++) {
|
|
207995
208020
|
const entry = entries[index];
|
|
@@ -207997,10 +208022,10 @@ async function getRegisteredWorktreeBranches(storage, projectId, projectPath) {
|
|
|
207997
208022
|
const existing = registered.find((row) => path7.resolve(row.checkout.worktree_path) === resolvedPath);
|
|
207998
208023
|
if (existing) {
|
|
207999
208024
|
if (existing.checkout.status === "creating" || existing.checkout.status === "error") {
|
|
208000
|
-
await
|
|
208025
|
+
await storage2.workspaceRegistry.setCheckoutStatus(existing.checkout.id, "ready");
|
|
208001
208026
|
}
|
|
208002
208027
|
if (index === 0 && existing.checkout.expected_branch === "" && entry.branch) {
|
|
208003
|
-
await
|
|
208028
|
+
await storage2.workspaceRegistry.registerReadyCheckout({
|
|
208004
208029
|
projectId,
|
|
208005
208030
|
branch: existing.workspace.branch,
|
|
208006
208031
|
targetId: "local",
|
|
@@ -208012,7 +208037,7 @@ async function getRegisteredWorktreeBranches(storage, projectId, projectPath) {
|
|
|
208012
208037
|
}
|
|
208013
208038
|
if (registeredPaths.has(resolvedPath) || entry.branch === null && index > 0) continue;
|
|
208014
208039
|
const stableBranch = index === 0 ? "" : sessionBranchByPath.get(resolvedPath) ?? entry.branch;
|
|
208015
|
-
await
|
|
208040
|
+
await storage2.workspaceRegistry.registerReadyCheckout({
|
|
208016
208041
|
projectId,
|
|
208017
208042
|
branch: stableBranch,
|
|
208018
208043
|
targetId: "local",
|
|
@@ -208021,7 +208046,7 @@ async function getRegisteredWorktreeBranches(storage, projectId, projectPath) {
|
|
|
208021
208046
|
});
|
|
208022
208047
|
registeredPaths.add(resolvedPath);
|
|
208023
208048
|
}
|
|
208024
|
-
registered = await
|
|
208049
|
+
registered = await storage2.workspaceRegistry.listByProject(projectId, "local");
|
|
208025
208050
|
const anchors = registered.map((row) => ({
|
|
208026
208051
|
branch: row.workspace.branch,
|
|
208027
208052
|
worktreePath: row.checkout.worktree_path,
|
|
@@ -208029,13 +208054,13 @@ async function getRegisteredWorktreeBranches(storage, projectId, projectPath) {
|
|
|
208029
208054
|
}));
|
|
208030
208055
|
return reconcileWorktreeBranches(projectPath, entries, sessionBranches, anchors);
|
|
208031
208056
|
}
|
|
208032
|
-
async function anchorRootWorkspaceBranch(
|
|
208057
|
+
async function anchorRootWorkspaceBranch(storage2, projectId, projectPath, observedBranch) {
|
|
208033
208058
|
invalidateWorktreeListCache(projectPath);
|
|
208034
208059
|
const rootEntry = readWorktreeListTolerant(projectPath)[0];
|
|
208035
208060
|
if (!rootEntry || rootEntry.branch !== observedBranch) {
|
|
208036
208061
|
return { anchored: false, currentBranch: rootEntry?.branch ?? null };
|
|
208037
208062
|
}
|
|
208038
|
-
await
|
|
208063
|
+
await storage2.workspaceRegistry.registerReadyCheckout({
|
|
208039
208064
|
projectId,
|
|
208040
208065
|
branch: "",
|
|
208041
208066
|
// The main-workspace identity sentinel; never the branch name.
|
|
@@ -208057,20 +208082,20 @@ function localBranchExists(projectPath, branch) {
|
|
|
208057
208082
|
return false;
|
|
208058
208083
|
}
|
|
208059
208084
|
}
|
|
208060
|
-
async function setRootWorkspaceAnchor(
|
|
208085
|
+
async function setRootWorkspaceAnchor(storage2, projectId, projectPath, branch) {
|
|
208061
208086
|
invalidateWorktreeListCache(projectPath);
|
|
208062
208087
|
const entries = readWorktreeListTolerant(projectPath);
|
|
208063
208088
|
const rootEntry = entries[0];
|
|
208064
208089
|
if (!rootEntry || !localBranchExists(projectPath, branch)) {
|
|
208065
208090
|
return { anchored: false, reason: rootEntry ? "unknown-branch" : "not-a-repository" };
|
|
208066
208091
|
}
|
|
208067
|
-
const registered = await
|
|
208092
|
+
const registered = await storage2.workspaceRegistry.listByProject(projectId, "local");
|
|
208068
208093
|
const takenByWorkspace = registered.some((row) => row.workspace.branch !== "" && row.workspace.branch === branch);
|
|
208069
208094
|
const takenByWorktree = entries.slice(1).some((entry) => entry.branch === branch);
|
|
208070
208095
|
if (takenByWorkspace || takenByWorktree) {
|
|
208071
208096
|
return { anchored: false, reason: "branch-is-another-workspace" };
|
|
208072
208097
|
}
|
|
208073
|
-
await
|
|
208098
|
+
await storage2.workspaceRegistry.registerReadyCheckout({
|
|
208074
208099
|
projectId,
|
|
208075
208100
|
branch: "",
|
|
208076
208101
|
// The main-workspace identity sentinel; never the branch name.
|
|
@@ -228912,8 +228937,8 @@ function parseChatProviderConfig(raw) {
|
|
|
228912
228937
|
return defaultConfig();
|
|
228913
228938
|
}
|
|
228914
228939
|
}
|
|
228915
|
-
async function getChatProviderConfig(
|
|
228916
|
-
const raw = await
|
|
228940
|
+
async function getChatProviderConfig(storage2, userId) {
|
|
228941
|
+
const raw = await storage2.userSettings.get(userId, "chat_provider");
|
|
228917
228942
|
return parseChatProviderConfig(raw);
|
|
228918
228943
|
}
|
|
228919
228944
|
function resolveModel(choice2, apiKeys) {
|
|
@@ -228925,12 +228950,12 @@ function isModelConfigured(config2, choice2) {
|
|
|
228925
228950
|
const def = PROVIDERS[choice2.provider];
|
|
228926
228951
|
return Boolean(config2.apiKeys[choice2.provider] || process.env[def.envKey]);
|
|
228927
228952
|
}
|
|
228928
|
-
async function resolveChatModel(
|
|
228929
|
-
const config2 = await getChatProviderConfig(
|
|
228953
|
+
async function resolveChatModel(storage2, userId) {
|
|
228954
|
+
const config2 = await getChatProviderConfig(storage2, userId);
|
|
228930
228955
|
return resolveModel(config2.main, config2.apiKeys);
|
|
228931
228956
|
}
|
|
228932
|
-
async function resolveFastChatModel(
|
|
228933
|
-
const config2 = await getChatProviderConfig(
|
|
228957
|
+
async function resolveFastChatModel(storage2, userId) {
|
|
228958
|
+
const config2 = await getChatProviderConfig(storage2, userId);
|
|
228934
228959
|
return resolveModel(config2.fast, config2.apiKeys);
|
|
228935
228960
|
}
|
|
228936
228961
|
|
|
@@ -228946,8 +228971,8 @@ function buildPrompt(userMessage) {
|
|
|
228946
228971
|
|
|
228947
228972
|
${input}`;
|
|
228948
228973
|
}
|
|
228949
|
-
async function isChatModelConfigured(
|
|
228950
|
-
const config2 = await getChatProviderConfig(
|
|
228974
|
+
async function isChatModelConfigured(storage2, userId) {
|
|
228975
|
+
const config2 = await getChatProviderConfig(storage2, userId);
|
|
228951
228976
|
return isModelConfigured(config2, config2.fast);
|
|
228952
228977
|
}
|
|
228953
228978
|
function extractUserText(content) {
|
|
@@ -228996,9 +229021,9 @@ async function generateSessionTitleWithModel(model, userMessage, options = {}) {
|
|
|
228996
229021
|
return null;
|
|
228997
229022
|
}
|
|
228998
229023
|
}
|
|
228999
|
-
async function generateSessionTitle(
|
|
229000
|
-
if (!await isChatModelConfigured(
|
|
229001
|
-
return generateSessionTitleWithModel(await resolveFastChatModel(
|
|
229024
|
+
async function generateSessionTitle(storage2, userMessage, userId) {
|
|
229025
|
+
if (!await isChatModelConfigured(storage2, userId)) return null;
|
|
229026
|
+
return generateSessionTitleWithModel(await resolveFastChatModel(storage2, userId), userMessage, { userId });
|
|
229002
229027
|
}
|
|
229003
229028
|
|
|
229004
229029
|
// src/utils/review-snapshot.ts
|
|
@@ -229149,11 +229174,11 @@ function computeScope(start, end, worktreePath) {
|
|
|
229149
229174
|
changed.sort();
|
|
229150
229175
|
return { changedFiles: changed, startHead: start.head };
|
|
229151
229176
|
}
|
|
229152
|
-
async function recordTurnSnapshot(
|
|
229177
|
+
async function recordTurnSnapshot(storage2, sessionId, turnEndIndex, worktreePath, captured) {
|
|
229153
229178
|
try {
|
|
229154
229179
|
const snap = captured ?? captureSnapshot(worktreePath);
|
|
229155
229180
|
if (!snap) return;
|
|
229156
|
-
await
|
|
229181
|
+
await storage2.turnSnapshots.create({
|
|
229157
229182
|
session_id: sessionId,
|
|
229158
229183
|
turn_end_index: turnEndIndex,
|
|
229159
229184
|
head: snap.head,
|
|
@@ -229163,8 +229188,8 @@ async function recordTurnSnapshot(storage, sessionId, turnEndIndex, worktreePath
|
|
|
229163
229188
|
console.warn(`[ReviewSnapshot] failed to record snapshot for ${sessionId}@${turnEndIndex}:`, err.message);
|
|
229164
229189
|
}
|
|
229165
229190
|
}
|
|
229166
|
-
async function resolveStartSnapshot(
|
|
229167
|
-
return span === "session_start" ?
|
|
229191
|
+
async function resolveStartSnapshot(storage2, sessionId, span, turnEndIndex) {
|
|
229192
|
+
return span === "session_start" ? storage2.turnSnapshots.getSessionStart(sessionId) : storage2.turnSnapshots.getStartBoundary(sessionId, turnEndIndex);
|
|
229168
229193
|
}
|
|
229169
229194
|
|
|
229170
229195
|
// src/branch-activity.ts
|
|
@@ -229516,8 +229541,8 @@ var AgentSessionManager = class {
|
|
|
229516
229541
|
/** Grace window before committing a held completion (injectable for tests). */
|
|
229517
229542
|
completionGraceMs;
|
|
229518
229543
|
workflowSuppressionCheck = null;
|
|
229519
|
-
constructor(
|
|
229520
|
-
this.storage =
|
|
229544
|
+
constructor(storage2, opts) {
|
|
229545
|
+
this.storage = storage2;
|
|
229521
229546
|
this.completionGraceMs = opts?.completionGraceMs ?? COMPLETION_GRACE_MS;
|
|
229522
229547
|
}
|
|
229523
229548
|
async resolveSessionWorktreePath(session, legacyProjectPath) {
|
|
@@ -231892,6 +231917,68 @@ var AgentSessionManager = class {
|
|
|
231892
231917
|
// src/chat-session-manager.ts
|
|
231893
231918
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
231894
231919
|
|
|
231920
|
+
// src/trace-context.ts
|
|
231921
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
231922
|
+
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
231923
|
+
var VERSION8 = "00";
|
|
231924
|
+
var INVALID_VERSION = "ff";
|
|
231925
|
+
var ZERO_TRACE_ID = "0".repeat(32);
|
|
231926
|
+
var ZERO_SPAN_ID = "0".repeat(16);
|
|
231927
|
+
var HEX_2 = /^[0-9a-f]{2}$/;
|
|
231928
|
+
var HEX_16 = /^[0-9a-f]{16}$/;
|
|
231929
|
+
var HEX_32 = /^[0-9a-f]{32}$/;
|
|
231930
|
+
function parseTraceparent(value) {
|
|
231931
|
+
const raw = Array.isArray(value) ? value[0] : value;
|
|
231932
|
+
if (typeof raw !== "string") return null;
|
|
231933
|
+
const parts = raw.split("-");
|
|
231934
|
+
if (parts.length < 4) return null;
|
|
231935
|
+
const [version2, traceId, spanId, flags] = parts;
|
|
231936
|
+
if (!HEX_2.test(version2) || version2 === INVALID_VERSION) return null;
|
|
231937
|
+
if (version2 === VERSION8 && parts.length !== 4) return null;
|
|
231938
|
+
if (!HEX_32.test(traceId) || traceId === ZERO_TRACE_ID) return null;
|
|
231939
|
+
if (!HEX_16.test(spanId) || spanId === ZERO_SPAN_ID) return null;
|
|
231940
|
+
if (!HEX_2.test(flags)) return null;
|
|
231941
|
+
return { traceId, spanId, flags };
|
|
231942
|
+
}
|
|
231943
|
+
function formatTraceparent(ctx) {
|
|
231944
|
+
return `${VERSION8}-${ctx.traceId}-${ctx.spanId}-${ctx.sampled ? "01" : "00"}`;
|
|
231945
|
+
}
|
|
231946
|
+
function newTraceId() {
|
|
231947
|
+
return randomBytes2(16).toString("hex");
|
|
231948
|
+
}
|
|
231949
|
+
function newSpanId() {
|
|
231950
|
+
return randomBytes2(8).toString("hex");
|
|
231951
|
+
}
|
|
231952
|
+
function newTraceContext(incoming) {
|
|
231953
|
+
const parsed = parseTraceparent(incoming);
|
|
231954
|
+
if (parsed) {
|
|
231955
|
+
return {
|
|
231956
|
+
traceId: parsed.traceId,
|
|
231957
|
+
spanId: newSpanId(),
|
|
231958
|
+
parentSpanId: parsed.spanId,
|
|
231959
|
+
sampled: (parseInt(parsed.flags, 16) & 1) === 1,
|
|
231960
|
+
continued: true
|
|
231961
|
+
};
|
|
231962
|
+
}
|
|
231963
|
+
return {
|
|
231964
|
+
traceId: newTraceId(),
|
|
231965
|
+
spanId: newSpanId(),
|
|
231966
|
+
sampled: true,
|
|
231967
|
+
continued: false
|
|
231968
|
+
};
|
|
231969
|
+
}
|
|
231970
|
+
var storage = new AsyncLocalStorage();
|
|
231971
|
+
function runWithTraceContext(ctx, fn) {
|
|
231972
|
+
return storage.run(ctx, fn);
|
|
231973
|
+
}
|
|
231974
|
+
function getTraceContext() {
|
|
231975
|
+
return storage.getStore();
|
|
231976
|
+
}
|
|
231977
|
+
function outboundTraceparent() {
|
|
231978
|
+
const ctx = storage.getStore();
|
|
231979
|
+
return ctx ? formatTraceparent(ctx) : void 0;
|
|
231980
|
+
}
|
|
231981
|
+
|
|
231895
231982
|
// src/utils/remote-proxy.ts
|
|
231896
231983
|
function proxyStatus(result, fallback = 502) {
|
|
231897
231984
|
return result.status > 0 ? result.status : fallback;
|
|
@@ -231899,7 +231986,12 @@ function proxyStatus(result, fallback = 502) {
|
|
|
231899
231986
|
async function proxyToRemoteAuto(remoteServerId, method, apiPath, body, options) {
|
|
231900
231987
|
const rcm = options?.reverseConnectManager;
|
|
231901
231988
|
if (rcm && rcm.isConnected(remoteServerId)) {
|
|
231902
|
-
|
|
231989
|
+
const traceparent = outboundTraceparent();
|
|
231990
|
+
const headers = {
|
|
231991
|
+
...traceparent ? { traceparent } : {},
|
|
231992
|
+
...options?.headers
|
|
231993
|
+
};
|
|
231994
|
+
return rcm.sendHttpRequest(remoteServerId, method, apiPath, body, options?.timeoutMs, headers);
|
|
231903
231995
|
}
|
|
231904
231996
|
return {
|
|
231905
231997
|
ok: false,
|
|
@@ -232040,7 +232132,7 @@ function runUpdatedFrameForSubscribers(evt) {
|
|
|
232040
232132
|
}
|
|
232041
232133
|
|
|
232042
232134
|
// src/utils/cross-remote-token.ts
|
|
232043
|
-
import { createHmac as createHmac2, randomBytes as
|
|
232135
|
+
import { createHmac as createHmac2, randomBytes as randomBytes3, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
232044
232136
|
var CROSS_REMOTE_SECRET_SETTING = "cross_remote_token_secret";
|
|
232045
232137
|
var CROSS_REMOTE_TOKEN_TTL_MS = 864e5;
|
|
232046
232138
|
var sign2 = (secret, body) => createHmac2("sha256", secret).update(body).digest("base64url");
|
|
@@ -232076,10 +232168,10 @@ function verifyCrossRemoteToken(secret, token, nowMs) {
|
|
|
232076
232168
|
if (nowMs >= wire.exp) return null;
|
|
232077
232169
|
return { userId: wire.u, sessionId: wire.s, sourceRemoteServerId: wire.src };
|
|
232078
232170
|
}
|
|
232079
|
-
async function getCrossRemoteSecret(
|
|
232080
|
-
return
|
|
232171
|
+
async function getCrossRemoteSecret(storage2) {
|
|
232172
|
+
return storage2.settings.getOrCreate(
|
|
232081
232173
|
CROSS_REMOTE_SECRET_SETTING,
|
|
232082
|
-
() =>
|
|
232174
|
+
() => randomBytes3(32).toString("hex")
|
|
232083
232175
|
);
|
|
232084
232176
|
}
|
|
232085
232177
|
|
|
@@ -232633,8 +232725,8 @@ function groupByServer(mappings) {
|
|
|
232633
232725
|
}
|
|
232634
232726
|
|
|
232635
232727
|
// src/remote-agent-sessions.ts
|
|
232636
|
-
async function bindRemoteSessionMapping(
|
|
232637
|
-
const mappingRepo = opts.mappingRepo ??
|
|
232728
|
+
async function bindRemoteSessionMapping(storage2, opts) {
|
|
232729
|
+
const mappingRepo = opts.mappingRepo ?? storage2.remoteSessionMappings;
|
|
232638
232730
|
const existingMapping = await mappingRepo.getByLocal(opts.localSessionId);
|
|
232639
232731
|
if (existingMapping?.workspace_checkout_id) {
|
|
232640
232732
|
if (existingMapping.project_id !== opts.projectId || existingMapping.remote_server_id !== opts.remoteServerId || existingMapping.remote_session_id !== opts.remoteSessionId || (existingMapping.branch ?? "") !== (opts.branch ?? "")) {
|
|
@@ -232644,13 +232736,13 @@ async function bindRemoteSessionMapping(storage, opts) {
|
|
|
232644
232736
|
}
|
|
232645
232737
|
const branchKey = opts.branch ?? "";
|
|
232646
232738
|
const fallbackPath = opts.branch ? conventionalWorktreePath(opts.remotePath, opts.branch) : opts.remotePath;
|
|
232647
|
-
let registered = await
|
|
232739
|
+
let registered = await storage2.workspaceRegistry.getByProjectBranch(
|
|
232648
232740
|
opts.projectId,
|
|
232649
232741
|
branchKey,
|
|
232650
232742
|
opts.remoteServerId
|
|
232651
232743
|
);
|
|
232652
232744
|
if (!registered || opts.reportedWorktreePath && (registered.checkout.path_source !== "reported" || registered.checkout.worktree_path !== opts.reportedWorktreePath)) {
|
|
232653
|
-
registered = await
|
|
232745
|
+
registered = await storage2.workspaceRegistry.registerReadyCheckout({
|
|
232654
232746
|
projectId: opts.projectId,
|
|
232655
232747
|
branch: branchKey,
|
|
232656
232748
|
targetId: opts.remoteServerId,
|
|
@@ -233182,11 +233274,11 @@ function isSequencePrefix(cached2, replay) {
|
|
|
233182
233274
|
}
|
|
233183
233275
|
return true;
|
|
233184
233276
|
}
|
|
233185
|
-
async function persistRemoteSessionActivityFrame(
|
|
233277
|
+
async function persistRemoteSessionActivityFrame(storage2, sessionId, remoteInfo, parsed, activityAt = Date.now()) {
|
|
233186
233278
|
const projectId = projectIdFromRemoteSessionId(sessionId, remoteInfo);
|
|
233187
233279
|
const statusEvent = statusEventFromRemotePatch(parsed, sessionId, remoteInfo);
|
|
233188
233280
|
if (statusEvent) {
|
|
233189
|
-
return
|
|
233281
|
+
return storage2.searchCache.updateRemoteSessionActivity({
|
|
233190
233282
|
localSessionId: sessionId,
|
|
233191
233283
|
projectId,
|
|
233192
233284
|
targetId: remoteInfo.remoteServerId,
|
|
@@ -233197,7 +233289,7 @@ async function persistRemoteSessionActivityFrame(storage, sessionId, remoteInfo,
|
|
|
233197
233289
|
});
|
|
233198
233290
|
}
|
|
233199
233291
|
if ("taskCompleted" in parsed) {
|
|
233200
|
-
return
|
|
233292
|
+
return storage2.searchCache.updateRemoteSessionActivity({
|
|
233201
233293
|
localSessionId: sessionId,
|
|
233202
233294
|
projectId,
|
|
233203
233295
|
targetId: remoteInfo.remoteServerId,
|
|
@@ -233208,7 +233300,7 @@ async function persistRemoteSessionActivityFrame(storage, sessionId, remoteInfo,
|
|
|
233208
233300
|
});
|
|
233209
233301
|
}
|
|
233210
233302
|
if ("error" in parsed) {
|
|
233211
|
-
return
|
|
233303
|
+
return storage2.searchCache.updateRemoteSessionActivity({
|
|
233212
233304
|
localSessionId: sessionId,
|
|
233213
233305
|
projectId,
|
|
233214
233306
|
targetId: remoteInfo.remoteServerId,
|
|
@@ -233219,7 +233311,7 @@ async function persistRemoteSessionActivityFrame(storage, sessionId, remoteInfo,
|
|
|
233219
233311
|
}
|
|
233220
233312
|
return false;
|
|
233221
233313
|
}
|
|
233222
|
-
function connectPersistentRemoteWs(sessionId, remoteInfo, cache2, reverseConnectManager, eventBus, agentSessionManager,
|
|
233314
|
+
function connectPersistentRemoteWs(sessionId, remoteInfo, cache2, reverseConnectManager, eventBus, agentSessionManager, storage2, requestedHistory) {
|
|
233223
233315
|
const hasCachedData = cache2.hasData(sessionId);
|
|
233224
233316
|
console.log(`[AgentWS] Opening persistent remote WS for ${sessionId} (cached=${hasCachedData})`);
|
|
233225
233317
|
if (!reverseConnectManager || !reverseConnectManager.isConnected(remoteInfo.remoteServerId)) {
|
|
@@ -233233,12 +233325,15 @@ function connectPersistentRemoteWs(sessionId, remoteInfo, cache2, reverseConnect
|
|
|
233233
233325
|
const upstreamEpoch = requestedHistory?.historyEpoch ?? cachedHead?.historyEpoch ?? void 0;
|
|
233234
233326
|
const upstreamAfter = requestedHistory?.afterEntryIndex ?? (upstreamEpoch !== void 0 ? cachedHead?.lastTurnEndEntryIndex ?? void 0 : void 0);
|
|
233235
233327
|
const upstreamParams = new URLSearchParams();
|
|
233236
|
-
if (upstreamEpoch !== void 0 && upstreamAfter !== void 0) {
|
|
233328
|
+
if (hasCachedData && upstreamEpoch !== void 0 && upstreamAfter !== void 0) {
|
|
233237
233329
|
upstreamParams.set("after", String(upstreamAfter));
|
|
233238
233330
|
upstreamParams.set("epoch", String(upstreamEpoch));
|
|
233239
233331
|
}
|
|
233240
233332
|
const usesBoundedReplay = upstreamParams.size > 0;
|
|
233241
233333
|
const wsPath = `/api/agent-sessions/${encodeURIComponent(remoteInfo.remoteSessionId)}/stream${usesBoundedReplay ? `?${upstreamParams}` : ""}`;
|
|
233334
|
+
if (!hasCachedData) {
|
|
233335
|
+
cache2.declareCoverage(sessionId, { epoch: upstreamEpoch ?? null, start: 0 });
|
|
233336
|
+
}
|
|
233242
233337
|
const adapter = new VirtualWsAdapter(
|
|
233243
233338
|
(data) => reverseConnectManager.sendChannelData(remoteInfo.remoteServerId, channelId, data),
|
|
233244
233339
|
() => reverseConnectManager.closeChannel(remoteInfo.remoteServerId, channelId)
|
|
@@ -233274,8 +233369,8 @@ function connectPersistentRemoteWs(sessionId, remoteInfo, cache2, reverseConnect
|
|
|
233274
233369
|
if (statusEvent) {
|
|
233275
233370
|
cache2.setSessionStatus(sessionId, statusEvent.status);
|
|
233276
233371
|
let activityReady = true;
|
|
233277
|
-
if (
|
|
233278
|
-
activityReady = await persistRemoteSessionActivityFrame(
|
|
233372
|
+
if (storage2) {
|
|
233373
|
+
activityReady = await persistRemoteSessionActivityFrame(storage2, sessionId, remoteInfo, parsed).catch((error48) => {
|
|
233279
233374
|
console.error(`[AgentWS] activity write-through failed for ${sessionId}:`, error48);
|
|
233280
233375
|
return false;
|
|
233281
233376
|
});
|
|
@@ -233297,8 +233392,8 @@ function connectPersistentRemoteWs(sessionId, remoteInfo, cache2, reverseConnect
|
|
|
233297
233392
|
cache2.appendMessage(sessionId, raw, false);
|
|
233298
233393
|
cache2.broadcast(sessionId, raw);
|
|
233299
233394
|
let activityReady = true;
|
|
233300
|
-
if (
|
|
233301
|
-
activityReady = await persistRemoteSessionActivityFrame(
|
|
233395
|
+
if (storage2) {
|
|
233396
|
+
activityReady = await persistRemoteSessionActivityFrame(storage2, sessionId, remoteInfo, parsed).catch((error48) => {
|
|
233302
233397
|
console.error(`[AgentWS] completion write-through failed for ${sessionId}:`, error48);
|
|
233303
233398
|
return false;
|
|
233304
233399
|
});
|
|
@@ -233353,8 +233448,8 @@ function connectPersistentRemoteWs(sessionId, remoteInfo, cache2, reverseConnect
|
|
|
233353
233448
|
cache2.appendMessage(sessionId, raw, false);
|
|
233354
233449
|
cache2.broadcast(sessionId, raw);
|
|
233355
233450
|
let activityReady = true;
|
|
233356
|
-
if (
|
|
233357
|
-
activityReady = await persistRemoteSessionActivityFrame(
|
|
233451
|
+
if (storage2) {
|
|
233452
|
+
activityReady = await persistRemoteSessionActivityFrame(storage2, sessionId, remoteInfo, parsed).catch((error48) => {
|
|
233358
233453
|
console.error(`[AgentWS] error write-through failed for ${sessionId}:`, error48);
|
|
233359
233454
|
return false;
|
|
233360
233455
|
});
|
|
@@ -233472,10 +233567,10 @@ function connectPersistentRemoteWs(sessionId, remoteInfo, cache2, reverseConnect
|
|
|
233472
233567
|
cache2.setRemoteWs(sessionId, null);
|
|
233473
233568
|
const entry = cache2.get(sessionId);
|
|
233474
233569
|
if (!entry || entry.finished) return;
|
|
233475
|
-
scheduleRemoteReconnect(sessionId, remoteInfo, cache2, reverseConnectManager, eventBus, agentSessionManager,
|
|
233570
|
+
scheduleRemoteReconnect(sessionId, remoteInfo, cache2, reverseConnectManager, eventBus, agentSessionManager, storage2);
|
|
233476
233571
|
});
|
|
233477
233572
|
}
|
|
233478
|
-
function scheduleRemoteReconnect(sessionId, remoteInfo, cache2, reverseConnectManager, eventBus, agentSessionManager,
|
|
233573
|
+
function scheduleRemoteReconnect(sessionId, remoteInfo, cache2, reverseConnectManager, eventBus, agentSessionManager, storage2) {
|
|
233479
233574
|
const entry = cache2.get(sessionId);
|
|
233480
233575
|
if (!entry || entry.finished) return;
|
|
233481
233576
|
const attempt = cache2.getReconnectAttempt(sessionId);
|
|
@@ -233497,7 +233592,7 @@ function scheduleRemoteReconnect(sessionId, remoteInfo, cache2, reverseConnectMa
|
|
|
233497
233592
|
cache2.setReconnecting(sessionId, false);
|
|
233498
233593
|
return;
|
|
233499
233594
|
}
|
|
233500
|
-
connectPersistentRemoteWs(sessionId, remoteInfo, cache2, reverseConnectManager, eventBus, agentSessionManager,
|
|
233595
|
+
connectPersistentRemoteWs(sessionId, remoteInfo, cache2, reverseConnectManager, eventBus, agentSessionManager, storage2);
|
|
233501
233596
|
}, totalDelay);
|
|
233502
233597
|
cache2.setReconnectTimer(sessionId, timer);
|
|
233503
233598
|
}
|
|
@@ -233642,8 +233737,8 @@ var ChatSessionManager = class {
|
|
|
233642
233737
|
workflowEngine = null;
|
|
233643
233738
|
/** Pending browser commands waiting for iframe response: commandId → resolve */
|
|
233644
233739
|
pendingBrowserCommands = /* @__PURE__ */ new Map();
|
|
233645
|
-
constructor(
|
|
233646
|
-
this.storage =
|
|
233740
|
+
constructor(storage2, processManager, agentSessionManager, remoteSessionMap, remoteExecutorMap, remotePatchCache, reverseConnectManager, browserManager) {
|
|
233741
|
+
this.storage = storage2;
|
|
233647
233742
|
this.processManager = processManager;
|
|
233648
233743
|
this.agentSessionManager = agentSessionManager;
|
|
233649
233744
|
this.remoteSessionMap = remoteSessionMap;
|
|
@@ -234558,7 +234653,7 @@ var ChatSessionManager = class {
|
|
|
234558
234653
|
return sections.join("\n");
|
|
234559
234654
|
}
|
|
234560
234655
|
createTools(projectId, branch, sessionId) {
|
|
234561
|
-
const
|
|
234656
|
+
const storage2 = this.storage;
|
|
234562
234657
|
const processManager = this.processManager;
|
|
234563
234658
|
const turnStartedAt = (sessionId ? this.sessions.get(sessionId)?.turnStartedAt : null) ?? null;
|
|
234564
234659
|
const wokenByEvent = (sessionId ? this.sessions.get(sessionId)?.wokenByEvent : false) ?? false;
|
|
@@ -234703,7 +234798,7 @@ var ChatSessionManager = class {
|
|
|
234703
234798
|
if (!sessionId) {
|
|
234704
234799
|
return { success: false, message: "No session context available." };
|
|
234705
234800
|
}
|
|
234706
|
-
const project = await
|
|
234801
|
+
const project = await storage2.projects.getById(projectId);
|
|
234707
234802
|
const agentMode = project?.agent_mode;
|
|
234708
234803
|
if (project && agentMode && agentMode !== "local") {
|
|
234709
234804
|
return await this.spawnRemoteAgentSession({ projectId, branch, agentMode, prompt, agentType, chatSessionId: sessionId });
|
|
@@ -234756,12 +234851,12 @@ var ChatSessionManager = class {
|
|
|
234756
234851
|
if (!sessionId) {
|
|
234757
234852
|
return { success: false, message: "No session context available." };
|
|
234758
234853
|
}
|
|
234759
|
-
const sendProject = await
|
|
234854
|
+
const sendProject = await storage2.projects.getById(projectId);
|
|
234760
234855
|
const sendAgentMode = sendProject?.agent_mode;
|
|
234761
234856
|
if (sendProject && sendAgentMode && sendAgentMode !== "local") {
|
|
234762
234857
|
return await this.sendToRemoteAgentSession({ projectId, branch, message, chatSessionId: sessionId });
|
|
234763
234858
|
}
|
|
234764
|
-
const project = await
|
|
234859
|
+
const project = await storage2.projects.getById(projectId);
|
|
234765
234860
|
const target = agentSessionManager.getSessionByBranch(projectId, branch);
|
|
234766
234861
|
if (!target) {
|
|
234767
234862
|
return {
|
|
@@ -234794,14 +234889,14 @@ var ChatSessionManager = class {
|
|
|
234794
234889
|
tailLines: external_exports.number().min(1).max(100).default(20).describe("Number of recent output lines to include per executor")
|
|
234795
234890
|
}),
|
|
234796
234891
|
execute: async ({ tailLines }) => {
|
|
234797
|
-
const workspace = await
|
|
234892
|
+
const workspace = await storage2.workspaceRegistry.getWorkspaceByProjectBranch(projectId, branch ?? "");
|
|
234798
234893
|
if (!workspace) {
|
|
234799
234894
|
return { executors: [], message: "No workspace found for this branch." };
|
|
234800
234895
|
}
|
|
234801
|
-
const executors = await
|
|
234896
|
+
const executors = await storage2.executors.getByWorkspaceId(workspace.id);
|
|
234802
234897
|
const now3 = Date.now();
|
|
234803
234898
|
const results = await Promise.all(executors.map(async (executor) => {
|
|
234804
|
-
const lastRow = await
|
|
234899
|
+
const lastRow = await storage2.executorProcesses.getLastByExecutorId(executor.id);
|
|
234805
234900
|
const liveProcesses = processManager.getProcessesByExecutorId(executor.id);
|
|
234806
234901
|
const latestLive = liveProcesses[liveProcesses.length - 1];
|
|
234807
234902
|
if (!lastRow) {
|
|
@@ -234840,11 +234935,11 @@ var ChatSessionManager = class {
|
|
|
234840
234935
|
remote: external_exports.string().optional().describe("Remote server name or ID to run the executor on. If omitted, uses project executor_mode or runs locally.")
|
|
234841
234936
|
}),
|
|
234842
234937
|
execute: async ({ executorName, remote }) => {
|
|
234843
|
-
const workspace = await
|
|
234938
|
+
const workspace = await storage2.workspaceRegistry.getWorkspaceByProjectBranch(projectId, branch ?? "");
|
|
234844
234939
|
if (!workspace) {
|
|
234845
234940
|
return { success: false, message: "No workspace found for this branch." };
|
|
234846
234941
|
}
|
|
234847
|
-
const executors = await
|
|
234942
|
+
const executors = await storage2.executors.getByWorkspaceId(workspace.id);
|
|
234848
234943
|
const executor = executors.find(
|
|
234849
234944
|
(e) => e.name.toLowerCase() === executorName.toLowerCase()
|
|
234850
234945
|
);
|
|
@@ -234857,26 +234952,26 @@ var ChatSessionManager = class {
|
|
|
234857
234952
|
}
|
|
234858
234953
|
let remoteServerId = remote;
|
|
234859
234954
|
if (remote) {
|
|
234860
|
-
const byId = await
|
|
234955
|
+
const byId = await storage2.remoteServers.getById(remote);
|
|
234861
234956
|
if (!byId) {
|
|
234862
|
-
const allServers = await
|
|
234957
|
+
const allServers = await storage2.remoteServers.getAll();
|
|
234863
234958
|
const byName = allServers.find((s3) => s3.name.toLowerCase() === remote.toLowerCase());
|
|
234864
234959
|
if (byName) {
|
|
234865
234960
|
remoteServerId = byName.id;
|
|
234866
234961
|
}
|
|
234867
234962
|
}
|
|
234868
234963
|
}
|
|
234869
|
-
const project = await
|
|
234964
|
+
const project = await storage2.projects.getById(projectId);
|
|
234870
234965
|
let executorMode = remoteServerId || project?.executor_mode;
|
|
234871
234966
|
let resolvedRemote = executorMode && executorMode !== "local" ? executorMode : void 0;
|
|
234872
234967
|
if (!resolvedRemote && !project?.path) {
|
|
234873
|
-
const remotes = await
|
|
234968
|
+
const remotes = await storage2.projectRemotes.getByProject(projectId);
|
|
234874
234969
|
if (remotes.length > 0) {
|
|
234875
234970
|
resolvedRemote = remotes[0].remote_server_id;
|
|
234876
234971
|
}
|
|
234877
234972
|
}
|
|
234878
234973
|
if (resolvedRemote) {
|
|
234879
|
-
const remoteConfig = await
|
|
234974
|
+
const remoteConfig = await storage2.projectRemotes.getByProjectAndServer(projectId, resolvedRemote);
|
|
234880
234975
|
if (!remoteConfig) {
|
|
234881
234976
|
return { success: false, message: `Remote server "${resolvedRemote}" not configured for this project.` };
|
|
234882
234977
|
}
|
|
@@ -234980,11 +235075,11 @@ var ChatSessionManager = class {
|
|
|
234980
235075
|
remote: external_exports.string().optional().describe("Remote server name or ID where the executor is running. If omitted, auto-detects.")
|
|
234981
235076
|
}),
|
|
234982
235077
|
execute: async ({ executorName, remote }) => {
|
|
234983
|
-
const workspace = await
|
|
235078
|
+
const workspace = await storage2.workspaceRegistry.getWorkspaceByProjectBranch(projectId, branch ?? "");
|
|
234984
235079
|
if (!workspace) {
|
|
234985
235080
|
return { success: false, message: "No workspace found for this branch." };
|
|
234986
235081
|
}
|
|
234987
|
-
const executors = await
|
|
235082
|
+
const executors = await storage2.executors.getByWorkspaceId(workspace.id);
|
|
234988
235083
|
const executor = executors.find(
|
|
234989
235084
|
(e) => e.name.toLowerCase() === executorName.toLowerCase()
|
|
234990
235085
|
);
|
|
@@ -234997,9 +235092,9 @@ var ChatSessionManager = class {
|
|
|
234997
235092
|
}
|
|
234998
235093
|
let remoteServerId = remote;
|
|
234999
235094
|
if (remote) {
|
|
235000
|
-
const byId = await
|
|
235095
|
+
const byId = await storage2.remoteServers.getById(remote);
|
|
235001
235096
|
if (!byId) {
|
|
235002
|
-
const allServers = await
|
|
235097
|
+
const allServers = await storage2.remoteServers.getAll();
|
|
235003
235098
|
const byName = allServers.find((s3) => s3.name.toLowerCase() === remote.toLowerCase());
|
|
235004
235099
|
if (byName) {
|
|
235005
235100
|
remoteServerId = byName.id;
|
|
@@ -235018,7 +235113,7 @@ var ChatSessionManager = class {
|
|
|
235018
235113
|
resolvedRemote = runningRemotes[0];
|
|
235019
235114
|
} else if (runningRemotes.length > 1) {
|
|
235020
235115
|
const remoteNames = await Promise.all(runningRemotes.map(async (id) => {
|
|
235021
|
-
const server = await
|
|
235116
|
+
const server = await storage2.remoteServers.getById(id);
|
|
235022
235117
|
return server?.name ?? id;
|
|
235023
235118
|
}));
|
|
235024
235119
|
return {
|
|
@@ -235801,14 +235896,14 @@ import { createHash as createHash2, randomUUID as randomUUID5 } from "crypto";
|
|
|
235801
235896
|
|
|
235802
235897
|
// src/project-chat-context.ts
|
|
235803
235898
|
var PROJECT_CHAT_CONTEXT_REF_LIMIT = 100;
|
|
235804
|
-
async function listProjectChatPublicContextRefs(
|
|
235805
|
-
const refs = await
|
|
235899
|
+
async function listProjectChatPublicContextRefs(storage2, thread) {
|
|
235900
|
+
const refs = await storage2.projectChatContextRefs.listByThread(
|
|
235806
235901
|
thread.id,
|
|
235807
235902
|
thread.project_id,
|
|
235808
235903
|
thread.user_id,
|
|
235809
235904
|
PROJECT_CHAT_CONTEXT_REF_LIMIT
|
|
235810
235905
|
);
|
|
235811
|
-
const existing = new Map((await
|
|
235906
|
+
const existing = new Map((await storage2.projectChatContextRefs.resolveExisting(
|
|
235812
235907
|
thread.project_id,
|
|
235813
235908
|
refs.map(({ entity_type, entity_id }) => ({ entity_type, entity_id }))
|
|
235814
235909
|
)).map((resolved) => [`${resolved.entity_type}\0${resolved.entity_id}`, resolved.navigation]));
|
|
@@ -236178,19 +236273,19 @@ async function createProjectChatTools(options) {
|
|
|
236178
236273
|
projectId,
|
|
236179
236274
|
threadId,
|
|
236180
236275
|
userId,
|
|
236181
|
-
storage,
|
|
236276
|
+
storage: storage2,
|
|
236182
236277
|
agentSessionManager,
|
|
236183
236278
|
remoteSessions,
|
|
236184
236279
|
mutationServices,
|
|
236185
236280
|
onOperationMessage
|
|
236186
236281
|
} = options;
|
|
236187
|
-
const project = await
|
|
236282
|
+
const project = await storage2.projects.getById(projectId, userId);
|
|
236188
236283
|
if (!project) throw new Error("Project not found");
|
|
236189
|
-
const thread = await
|
|
236284
|
+
const thread = await storage2.projectChatThreads.getById(threadId, projectId, userId);
|
|
236190
236285
|
if (!thread) throw new Error("Project Chat thread not found");
|
|
236191
236286
|
const touchAll = async (entityType, ids) => {
|
|
236192
236287
|
if (ids.length === 0) return;
|
|
236193
|
-
const tracked = await
|
|
236288
|
+
const tracked = await storage2.projectChatContextRefs.touchMany(
|
|
236194
236289
|
threadId,
|
|
236195
236290
|
projectId,
|
|
236196
236291
|
userId,
|
|
@@ -236205,8 +236300,8 @@ async function createProjectChatTools(options) {
|
|
|
236205
236300
|
};
|
|
236206
236301
|
const revalidateScope = async () => {
|
|
236207
236302
|
const [ownedProject, ownedThread] = await Promise.all([
|
|
236208
|
-
|
|
236209
|
-
|
|
236303
|
+
storage2.projects.getById(projectId, userId),
|
|
236304
|
+
storage2.projectChatThreads.getById(threadId, projectId, userId)
|
|
236210
236305
|
]);
|
|
236211
236306
|
if (!ownedProject || !ownedThread) throw new Error("Project Chat scope is no longer authorized");
|
|
236212
236307
|
};
|
|
@@ -236221,7 +236316,7 @@ async function createProjectChatTools(options) {
|
|
|
236221
236316
|
const beginOperation = async (kind, entityType, entityId, details, ids = {}) => {
|
|
236222
236317
|
const operationId = ids.operationId ?? randomUUID4();
|
|
236223
236318
|
const idempotencyKey = ids.idempotencyKey ?? operationId;
|
|
236224
|
-
const row = await
|
|
236319
|
+
const row = await storage2.projectChatOperations.create({
|
|
236225
236320
|
id: operationId,
|
|
236226
236321
|
thread_id: threadId,
|
|
236227
236322
|
project_id: projectId,
|
|
@@ -236238,7 +236333,7 @@ async function createProjectChatTools(options) {
|
|
|
236238
236333
|
return row;
|
|
236239
236334
|
};
|
|
236240
236335
|
const finishOperation = async (operation, status, details, error48 = null) => {
|
|
236241
|
-
const current = await
|
|
236336
|
+
const current = await storage2.projectChatOperations.getById(
|
|
236242
236337
|
operation.id,
|
|
236243
236338
|
threadId,
|
|
236244
236339
|
projectId,
|
|
@@ -236248,7 +236343,7 @@ async function createProjectChatTools(options) {
|
|
|
236248
236343
|
const publicError = error48 === null ? null : sanitizeProjectChatPublicError(error48, "Operation failed");
|
|
236249
236344
|
const payload = { ...current.payload, status, ...details };
|
|
236250
236345
|
const content = projectChatPublicOperationContent(payload, publicError);
|
|
236251
|
-
const result = await
|
|
236346
|
+
const result = await storage2.projectChatOperations.transition({
|
|
236252
236347
|
id: operation.id,
|
|
236253
236348
|
thread_id: threadId,
|
|
236254
236349
|
project_id: projectId,
|
|
@@ -236268,7 +236363,7 @@ async function createProjectChatTools(options) {
|
|
|
236268
236363
|
return result.operation;
|
|
236269
236364
|
};
|
|
236270
236365
|
const markOperationRunning = async (operation, details) => {
|
|
236271
|
-
const current = await
|
|
236366
|
+
const current = await storage2.projectChatOperations.getById(
|
|
236272
236367
|
operation.id,
|
|
236273
236368
|
threadId,
|
|
236274
236369
|
projectId,
|
|
@@ -236281,9 +236376,9 @@ async function createProjectChatTools(options) {
|
|
|
236281
236376
|
return finishOperation(current, "running", details);
|
|
236282
236377
|
};
|
|
236283
236378
|
const workspaceCandidates = async () => {
|
|
236284
|
-
const project2 = await
|
|
236379
|
+
const project2 = await storage2.projects.getById(projectId, userId);
|
|
236285
236380
|
if (!project2) throw new Error("Project is no longer authorized");
|
|
236286
|
-
const rows = await
|
|
236381
|
+
const rows = await storage2.searchCache.listWorkspacesByProject(projectId, LIST_LIMIT + 1);
|
|
236287
236382
|
const candidates = rows.flatMap((row) => {
|
|
236288
236383
|
if (typeof row.targetId !== "string" || !isNullableString(row.branch)) return [];
|
|
236289
236384
|
if (row.targetId.length > TARGET_CHAR_LIMIT || (row.branch?.length ?? 0) > BRANCH_CHAR_LIMIT) return [];
|
|
@@ -236291,7 +236386,7 @@ async function createProjectChatTools(options) {
|
|
|
236291
236386
|
if (!isToolSelectorId(id)) return [];
|
|
236292
236387
|
return [{ id, target: row.targetId, branch: row.branch }];
|
|
236293
236388
|
});
|
|
236294
|
-
const authorized = await Promise.all(candidates.map(async (candidate) => candidate.target === "local" ? candidate : await
|
|
236389
|
+
const authorized = await Promise.all(candidates.map(async (candidate) => candidate.target === "local" ? candidate : await storage2.projectRemotes.getByProjectAndServer(projectId, candidate.target) ? candidate : void 0));
|
|
236295
236390
|
const available = authorized.filter((candidate) => Boolean(candidate));
|
|
236296
236391
|
return { items: available.slice(0, LIST_LIMIT), truncated: available.length > LIST_LIMIT };
|
|
236297
236392
|
};
|
|
@@ -236305,24 +236400,24 @@ async function createProjectChatTools(options) {
|
|
|
236305
236400
|
const candidate = (await workspaceCandidates()).items.find(({ id }) => id === workspaceId);
|
|
236306
236401
|
if (!candidate) throw new Error("Workspace is no longer available in this project");
|
|
236307
236402
|
if (candidate.target !== "local") {
|
|
236308
|
-
const association = await
|
|
236403
|
+
const association = await storage2.projectRemotes.getByProjectAndServer(projectId, candidate.target);
|
|
236309
236404
|
if (!association) throw new Error("Workspace is no longer available in this project");
|
|
236310
236405
|
}
|
|
236311
236406
|
return candidate;
|
|
236312
236407
|
};
|
|
236313
236408
|
const sessionExistsInScope = async (sessionId) => {
|
|
236314
|
-
const local = await
|
|
236315
|
-
if (local) return (await
|
|
236409
|
+
const local = await storage2.agentSessions.getById(sessionId);
|
|
236410
|
+
if (local) return (await storage2.agentSessions.getActivityById(sessionId, "project-chat"))?.projectId === projectId;
|
|
236316
236411
|
const mapping = await remoteSessions?.getMapping(sessionId);
|
|
236317
236412
|
if (!mapping || mapping.projectId !== projectId) return false;
|
|
236318
|
-
return Boolean(await
|
|
236413
|
+
return Boolean(await storage2.projectRemotes.getByProjectAndServer(
|
|
236319
236414
|
projectId,
|
|
236320
236415
|
mapping.remoteServerId
|
|
236321
236416
|
));
|
|
236322
236417
|
};
|
|
236323
236418
|
const rereadConfirmedSession = async (operation, sessionId) => {
|
|
236324
|
-
const local = await
|
|
236325
|
-
const localProjection = local ? await
|
|
236419
|
+
const local = await storage2.agentSessions.getById(sessionId);
|
|
236420
|
+
const localProjection = local ? await storage2.agentSessions.getActivityById(sessionId, "project-chat") : void 0;
|
|
236326
236421
|
if (local && localProjection?.projectId === projectId && local.status !== "running") {
|
|
236327
236422
|
const status = local.status === "stopped" && local.last_completed_at ? "completed" : "failed";
|
|
236328
236423
|
return finishOperation(operation, status, { sessionId }, status === "failed" ? "Agent session failed" : null);
|
|
@@ -236362,7 +236457,7 @@ async function createProjectChatTools(options) {
|
|
|
236362
236457
|
try {
|
|
236363
236458
|
await revalidateScope();
|
|
236364
236459
|
await validateAssignedBranch(assignedBranch);
|
|
236365
|
-
const task = await
|
|
236460
|
+
const task = await storage2.tasks.create({
|
|
236366
236461
|
id: taskId,
|
|
236367
236462
|
project_id: projectId,
|
|
236368
236463
|
title,
|
|
@@ -236376,7 +236471,7 @@ async function createProjectChatTools(options) {
|
|
|
236376
236471
|
return { ok: true, operationId: operation.id, taskId: task.id, status: "completed" };
|
|
236377
236472
|
} catch (error48) {
|
|
236378
236473
|
const message = boundedError(error48);
|
|
236379
|
-
const applied = await
|
|
236474
|
+
const applied = await storage2.tasks.getById(taskId);
|
|
236380
236475
|
if (applied?.project_id === projectId) {
|
|
236381
236476
|
return {
|
|
236382
236477
|
ok: false,
|
|
@@ -236398,7 +236493,7 @@ async function createProjectChatTools(options) {
|
|
|
236398
236493
|
execute: async ({ taskId, assignedBranch, ...patch }) => {
|
|
236399
236494
|
mutationService();
|
|
236400
236495
|
await revalidateScope();
|
|
236401
|
-
const target = await
|
|
236496
|
+
const target = await storage2.tasks.getById(taskId);
|
|
236402
236497
|
if (!target) throw new Error("Task not found");
|
|
236403
236498
|
if (target.project_id !== projectId) throw new Error("Object is not part of this project");
|
|
236404
236499
|
await validateAssignedBranch(assignedBranch);
|
|
@@ -236419,10 +236514,10 @@ async function createProjectChatTools(options) {
|
|
|
236419
236514
|
});
|
|
236420
236515
|
try {
|
|
236421
236516
|
await revalidateScope();
|
|
236422
|
-
const current = await
|
|
236517
|
+
const current = await storage2.tasks.getById(taskId);
|
|
236423
236518
|
if (!current || current.project_id !== projectId) throw new Error("Task is no longer authorized");
|
|
236424
236519
|
await validateAssignedBranch(assignedBranch);
|
|
236425
|
-
const updated = await
|
|
236520
|
+
const updated = await storage2.tasks.update(taskId, {
|
|
236426
236521
|
...patch,
|
|
236427
236522
|
...assignedBranch !== void 0 ? { assigned_branch: assignedBranch } : {}
|
|
236428
236523
|
});
|
|
@@ -236432,7 +236527,7 @@ async function createProjectChatTools(options) {
|
|
|
236432
236527
|
return { ok: true, operationId: operation.id, taskId, status: "completed" };
|
|
236433
236528
|
} catch (error48) {
|
|
236434
236529
|
const message = boundedError(error48);
|
|
236435
|
-
const applied = await
|
|
236530
|
+
const applied = await storage2.tasks.getById(taskId);
|
|
236436
236531
|
const current = applied && {
|
|
236437
236532
|
title: applied.title,
|
|
236438
236533
|
description: applied.description,
|
|
@@ -236483,7 +236578,7 @@ async function createProjectChatTools(options) {
|
|
|
236483
236578
|
"pending",
|
|
236484
236579
|
{ requestId: operation2.id, candidates: candidates.map(({ id, target, branch }) => ({ id, target, branch })) }
|
|
236485
236580
|
));
|
|
236486
|
-
const announced = await
|
|
236581
|
+
const announced = await storage2.projectChatOperations.announce({
|
|
236487
236582
|
id: operation2.id,
|
|
236488
236583
|
thread_id: threadId,
|
|
236489
236584
|
project_id: projectId,
|
|
@@ -236567,7 +236662,7 @@ async function createProjectChatTools(options) {
|
|
|
236567
236662
|
execute: async ({ requestId, workspaceId }) => {
|
|
236568
236663
|
const service = mutationService();
|
|
236569
236664
|
await revalidateScope();
|
|
236570
|
-
const operation = await
|
|
236665
|
+
const operation = await storage2.projectChatOperations.getById(
|
|
236571
236666
|
requestId,
|
|
236572
236667
|
threadId,
|
|
236573
236668
|
projectId,
|
|
@@ -236596,7 +236691,7 @@ async function createProjectChatTools(options) {
|
|
|
236596
236691
|
let current = operation;
|
|
236597
236692
|
for (let attempt = 0; attempt < 100 && current.status === "resolving"; attempt++) {
|
|
236598
236693
|
await new Promise((resolve3) => setTimeout(resolve3, 5));
|
|
236599
|
-
current = await
|
|
236694
|
+
current = await storage2.projectChatOperations.getById(
|
|
236600
236695
|
requestId,
|
|
236601
236696
|
threadId,
|
|
236602
236697
|
projectId,
|
|
@@ -236646,7 +236741,7 @@ async function createProjectChatTools(options) {
|
|
|
236646
236741
|
branch: workspace.branch,
|
|
236647
236742
|
initialInstructionDelivery: "pending"
|
|
236648
236743
|
};
|
|
236649
|
-
const claim = await
|
|
236744
|
+
const claim = await storage2.projectChatOperations.claimWorkspaceSelection({
|
|
236650
236745
|
id: operation.id,
|
|
236651
236746
|
thread_id: threadId,
|
|
236652
236747
|
project_id: projectId,
|
|
@@ -236674,7 +236769,7 @@ async function createProjectChatTools(options) {
|
|
|
236674
236769
|
}
|
|
236675
236770
|
for (let attempt = 0; attempt < 100 && correlated.status === "resolving"; attempt++) {
|
|
236676
236771
|
await new Promise((resolve3) => setTimeout(resolve3, 5));
|
|
236677
|
-
correlated = await
|
|
236772
|
+
correlated = await storage2.projectChatOperations.getById(
|
|
236678
236773
|
requestId,
|
|
236679
236774
|
threadId,
|
|
236680
236775
|
projectId,
|
|
@@ -236750,10 +236845,10 @@ async function createProjectChatTools(options) {
|
|
|
236750
236845
|
execute: async ({ sessionId, instruction }) => {
|
|
236751
236846
|
const service = mutationService();
|
|
236752
236847
|
await revalidateScope();
|
|
236753
|
-
const local = await
|
|
236848
|
+
const local = await storage2.agentSessions.getById(sessionId);
|
|
236754
236849
|
let target;
|
|
236755
236850
|
if (local) {
|
|
236756
|
-
const localProjectId = local.workspace_checkout_id ? (await
|
|
236851
|
+
const localProjectId = local.workspace_checkout_id ? (await storage2.agentSessions.getActivityById(sessionId, "project-chat"))?.projectId : local.project_id;
|
|
236757
236852
|
if (localProjectId !== projectId) {
|
|
236758
236853
|
throw new Error("Object is not part of this project");
|
|
236759
236854
|
}
|
|
@@ -236762,7 +236857,7 @@ async function createProjectChatTools(options) {
|
|
|
236762
236857
|
const mapping = await remoteSessions?.getMapping(sessionId);
|
|
236763
236858
|
if (!mapping) throw new Error("Agent session not found");
|
|
236764
236859
|
if (mapping.projectId !== projectId) throw new Error("Object is not part of this project");
|
|
236765
|
-
const association = await
|
|
236860
|
+
const association = await storage2.projectRemotes.getByProjectAndServer(projectId, mapping.remoteServerId);
|
|
236766
236861
|
if (!association) throw new Error("Agent session not found");
|
|
236767
236862
|
target = { remoteServerId: mapping.remoteServerId, remoteSessionId: mapping.remoteSessionId };
|
|
236768
236863
|
}
|
|
@@ -236776,8 +236871,8 @@ async function createProjectChatTools(options) {
|
|
|
236776
236871
|
try {
|
|
236777
236872
|
await revalidateScope();
|
|
236778
236873
|
if (target === "local") {
|
|
236779
|
-
const current = await
|
|
236780
|
-
const currentProjection = current && current.workspace_checkout_id ? await
|
|
236874
|
+
const current = await storage2.agentSessions.getById(sessionId);
|
|
236875
|
+
const currentProjection = current && current.workspace_checkout_id ? await storage2.agentSessions.getActivityById(sessionId, "project-chat") : void 0;
|
|
236781
236876
|
const currentProjectId = current?.workspace_checkout_id ? currentProjection?.projectId : current?.project_id;
|
|
236782
236877
|
if (!current || currentProjectId !== projectId) {
|
|
236783
236878
|
throw new Error("Agent session is no longer authorized");
|
|
@@ -236787,7 +236882,7 @@ async function createProjectChatTools(options) {
|
|
|
236787
236882
|
if (!current || current.projectId !== projectId || current.remoteServerId !== target.remoteServerId || current.remoteSessionId !== target.remoteSessionId) {
|
|
236788
236883
|
throw new Error("Agent session is no longer authorized");
|
|
236789
236884
|
}
|
|
236790
|
-
const association = await
|
|
236885
|
+
const association = await storage2.projectRemotes.getByProjectAndServer(
|
|
236791
236886
|
projectId,
|
|
236792
236887
|
current.remoteServerId
|
|
236793
236888
|
);
|
|
@@ -236823,7 +236918,7 @@ async function createProjectChatTools(options) {
|
|
|
236823
236918
|
execute: async ({ scheduleId }) => {
|
|
236824
236919
|
const service = mutationService();
|
|
236825
236920
|
await revalidateScope();
|
|
236826
|
-
const schedule = await
|
|
236921
|
+
const schedule = await storage2.scheduledTasks.getById(scheduleId);
|
|
236827
236922
|
if (!schedule) throw new Error("Schedule not found");
|
|
236828
236923
|
if (schedule.project_id !== projectId) throw new Error("Object is not part of this project");
|
|
236829
236924
|
const runId = randomUUID4();
|
|
@@ -236834,12 +236929,12 @@ async function createProjectChatTools(options) {
|
|
|
236834
236929
|
});
|
|
236835
236930
|
try {
|
|
236836
236931
|
await revalidateScope();
|
|
236837
|
-
const current = await
|
|
236932
|
+
const current = await storage2.scheduledTasks.getById(scheduleId);
|
|
236838
236933
|
if (!current || current.project_id !== projectId) throw new Error("Schedule is no longer authorized");
|
|
236839
236934
|
const result = await service.runScheduleNow(scheduleId, runId);
|
|
236840
236935
|
const [persisted, authorizedSchedule] = await Promise.all([
|
|
236841
|
-
|
|
236842
|
-
|
|
236936
|
+
storage2.scheduledTaskRuns.getById(runId),
|
|
236937
|
+
storage2.scheduledTasks.getById(scheduleId)
|
|
236843
236938
|
]);
|
|
236844
236939
|
if (!authorizedSchedule || authorizedSchedule.project_id !== projectId) {
|
|
236845
236940
|
throw new Error("Schedule is no longer authorized");
|
|
@@ -236851,7 +236946,7 @@ async function createProjectChatTools(options) {
|
|
|
236851
236946
|
throw new Error("error" in result ? result.error : "Schedule run identity mismatch");
|
|
236852
236947
|
}
|
|
236853
236948
|
const skipped = "error" in result ? persisted.status === "skipped" : result.skipped;
|
|
236854
|
-
const tracked = await
|
|
236949
|
+
const tracked = await storage2.projectChatContextRefs.touchMany(
|
|
236855
236950
|
threadId,
|
|
236856
236951
|
projectId,
|
|
236857
236952
|
userId,
|
|
@@ -236870,7 +236965,7 @@ async function createProjectChatTools(options) {
|
|
|
236870
236965
|
);
|
|
236871
236966
|
let final = transitioned;
|
|
236872
236967
|
if (status === "running") {
|
|
236873
|
-
const latest = await
|
|
236968
|
+
const latest = await storage2.scheduledTaskRuns.getById(runId);
|
|
236874
236969
|
if (latest?.project_id === projectId && latest.schedule_id === scheduleId && latest.status !== "starting" && latest.status !== "running") {
|
|
236875
236970
|
const latestStatus = latest.status === "completed" || latest.status === "skipped" ? "completed" : "failed";
|
|
236876
236971
|
final = await finishOperation(
|
|
@@ -236883,7 +236978,7 @@ async function createProjectChatTools(options) {
|
|
|
236883
236978
|
}
|
|
236884
236979
|
return { ok: final.status !== "failed", operationId: operation.id, scheduleId, runId, status: final.status, skipped };
|
|
236885
236980
|
} catch (error48) {
|
|
236886
|
-
const persisted = await
|
|
236981
|
+
const persisted = await storage2.scheduledTaskRuns.getById(runId);
|
|
236887
236982
|
if (persisted?.project_id === projectId && persisted.schedule_id === scheduleId) {
|
|
236888
236983
|
return {
|
|
236889
236984
|
ok: false,
|
|
@@ -236916,7 +237011,7 @@ async function createProjectChatTools(options) {
|
|
|
236916
237011
|
status: external_exports.enum(["todo", "in_progress", "done", "cancelled"]).optional()
|
|
236917
237012
|
}).strict(),
|
|
236918
237013
|
execute: readInScope(async ({ query, status }) => {
|
|
236919
|
-
const rows = await
|
|
237014
|
+
const rows = await storage2.tasks.queryByProject(projectId, { query, status, limit: LIST_LIMIT });
|
|
236920
237015
|
const validRows = rows.filter((row) => isToolSelectorId(row.id));
|
|
236921
237016
|
await touchAll("task", validRows.map((row) => row.id));
|
|
236922
237017
|
return {
|
|
@@ -236936,7 +237031,7 @@ async function createProjectChatTools(options) {
|
|
|
236936
237031
|
description: "Inspect one task by id, only if it belongs to this project.",
|
|
236937
237032
|
inputSchema: external_exports.object({ taskId: external_exports.string().min(1).max(MAX_TOOL_SELECTOR_ID) }).strict(),
|
|
236938
237033
|
execute: readInScope(async ({ taskId }) => {
|
|
236939
|
-
const row = await
|
|
237034
|
+
const row = await storage2.tasks.getById(taskId);
|
|
236940
237035
|
if (!row) throw new Error("Task not found");
|
|
236941
237036
|
if (row.project_id !== projectId) throw new Error("Object is not part of this project");
|
|
236942
237037
|
if (!isToolSelectorId(row.id)) throw new Error("Task not found");
|
|
@@ -236977,7 +237072,7 @@ async function createProjectChatTools(options) {
|
|
|
236977
237072
|
inputSchema: emptySchema,
|
|
236978
237073
|
execute: readInScope(async () => {
|
|
236979
237074
|
const [localRows, untrustedRemoteRows] = await Promise.all([
|
|
236980
|
-
|
|
237075
|
+
storage2.agentSessions.listRecentActivityByProject(projectId, LIST_LIMIT / 2, "project-chat"),
|
|
236981
237076
|
remoteSessions?.listByProject(projectId, LIST_LIMIT / 2) ?? Promise.resolve([])
|
|
236982
237077
|
]);
|
|
236983
237078
|
const remoteRows = safeArrayPrefix(untrustedRemoteRows, LIST_LIMIT / 2);
|
|
@@ -237043,9 +237138,9 @@ async function createProjectChatTools(options) {
|
|
|
237043
237138
|
description: "Return status and a server-bounded recent transcript for one project agent session.",
|
|
237044
237139
|
inputSchema: external_exports.object({ sessionId: external_exports.string().min(1).max(MAX_TOOL_SELECTOR_ID) }).strict(),
|
|
237045
237140
|
execute: readInScope(async ({ sessionId }) => {
|
|
237046
|
-
const local = await
|
|
237141
|
+
const local = await storage2.agentSessions.getById(sessionId);
|
|
237047
237142
|
if (local) {
|
|
237048
|
-
const projection = await
|
|
237143
|
+
const projection = await storage2.agentSessions.getActivityById(sessionId, "project-chat");
|
|
237049
237144
|
if (projection?.projectId !== projectId) throw new Error("Object is not part of this project");
|
|
237050
237145
|
if (!isToolSelectorId(local.id)) throw new Error("Agent session not found");
|
|
237051
237146
|
const detail2 = {
|
|
@@ -237118,7 +237213,7 @@ async function createProjectChatTools(options) {
|
|
|
237118
237213
|
description: "List schedules configured for this project without commands, prompts, or raw configuration.",
|
|
237119
237214
|
inputSchema: emptySchema,
|
|
237120
237215
|
execute: readInScope(async () => {
|
|
237121
|
-
const rows = await
|
|
237216
|
+
const rows = await storage2.scheduledTasks.listByProject(projectId, LIST_LIMIT);
|
|
237122
237217
|
const validRows = rows.filter((row) => isToolSelectorId(row.id));
|
|
237123
237218
|
await touchAll("schedule", validRows.map((row) => row.id));
|
|
237124
237219
|
return {
|
|
@@ -237140,7 +237235,7 @@ async function createProjectChatTools(options) {
|
|
|
237140
237235
|
description: "List recent runs across this project's schedules without raw output or reports.",
|
|
237141
237236
|
inputSchema: emptySchema,
|
|
237142
237237
|
execute: readInScope(async () => {
|
|
237143
|
-
const rows = await
|
|
237238
|
+
const rows = await storage2.scheduledTaskRuns.listRecentByProject(projectId, LIST_LIMIT);
|
|
237144
237239
|
const validRows = rows.filter((row) => isToolSelectorId(row.id));
|
|
237145
237240
|
await touchAll("schedule_run", validRows.map((row) => row.id));
|
|
237146
237241
|
return {
|
|
@@ -237160,9 +237255,9 @@ async function createProjectChatTools(options) {
|
|
|
237160
237255
|
description: "Inspect one project schedule run with server-bounded output and report previews.",
|
|
237161
237256
|
inputSchema: external_exports.object({ runId: external_exports.string().min(1).max(MAX_TOOL_SELECTOR_ID) }).strict(),
|
|
237162
237257
|
execute: readInScope(async ({ runId }) => {
|
|
237163
|
-
const run2 = await
|
|
237258
|
+
const run2 = await storage2.scheduledTaskRuns.getById(runId);
|
|
237164
237259
|
if (!run2) throw new Error("Schedule run not found");
|
|
237165
|
-
const schedule = await
|
|
237260
|
+
const schedule = await storage2.scheduledTasks.getById(run2.schedule_id);
|
|
237166
237261
|
if (!schedule) throw new Error("Schedule run not found");
|
|
237167
237262
|
if (schedule.project_id !== projectId) throw new Error("Object is not part of this project");
|
|
237168
237263
|
if (!isToolSelectorId(run2.id)) throw new Error("Schedule run not found");
|
|
@@ -237326,8 +237421,8 @@ async function* adaptProjectChatFullStream(fullStream, signal) {
|
|
|
237326
237421
|
if (pending) yield pending;
|
|
237327
237422
|
}
|
|
237328
237423
|
var DefaultProjectChatModelRunner = class {
|
|
237329
|
-
constructor(
|
|
237330
|
-
this.storage =
|
|
237424
|
+
constructor(storage2) {
|
|
237425
|
+
this.storage = storage2;
|
|
237331
237426
|
}
|
|
237332
237427
|
storage;
|
|
237333
237428
|
async *run(input) {
|
|
@@ -237389,9 +237484,9 @@ function projectChatAiTools(domainTools) {
|
|
|
237389
237484
|
return adapted;
|
|
237390
237485
|
}
|
|
237391
237486
|
var ProjectChatManager = class {
|
|
237392
|
-
constructor(
|
|
237393
|
-
this.storage =
|
|
237394
|
-
this.runner = runner ?? new DefaultProjectChatModelRunner(
|
|
237487
|
+
constructor(storage2, runner, options = {}) {
|
|
237488
|
+
this.storage = storage2;
|
|
237489
|
+
this.runner = runner ?? new DefaultProjectChatModelRunner(storage2);
|
|
237395
237490
|
this.drainTimeoutMs = options.drainTimeoutMs ?? 2e3;
|
|
237396
237491
|
this.idleEvictionMs = options.idleEvictionMs ?? 3e4;
|
|
237397
237492
|
this.terminalRetryDelayMs = options.terminalRetryDelayMs ?? 100;
|
|
@@ -239230,8 +239325,8 @@ var FINAL_VERDICT_PROMPT = [
|
|
|
239230
239325
|
].join("\n");
|
|
239231
239326
|
var REVIEWER_AGENT_TYPES = /* @__PURE__ */ new Set(["claude-code", "codex"]);
|
|
239232
239327
|
var WorkflowEngine = class {
|
|
239233
|
-
constructor(
|
|
239234
|
-
this.storage =
|
|
239328
|
+
constructor(storage2, agentOps) {
|
|
239329
|
+
this.storage = storage2;
|
|
239235
239330
|
this.agentOps = agentOps;
|
|
239236
239331
|
}
|
|
239237
239332
|
storage;
|
|
@@ -239794,6 +239889,11 @@ function percentile(sorted, fraction) {
|
|
|
239794
239889
|
const rank = Math.ceil(fraction * sorted.length);
|
|
239795
239890
|
return sorted[Math.min(sorted.length, Math.max(1, rank)) - 1];
|
|
239796
239891
|
}
|
|
239892
|
+
function coverageAdmitsReplay(coverage, clientEpoch, afterEntryIndex) {
|
|
239893
|
+
if (!coverage) return false;
|
|
239894
|
+
if (clientEpoch !== void 0 && coverage.epoch !== null && clientEpoch !== coverage.epoch) return false;
|
|
239895
|
+
return (afterEntryIndex ?? -1) + 1 >= coverage.start;
|
|
239896
|
+
}
|
|
239797
239897
|
var RemotePatchCache = class {
|
|
239798
239898
|
cache = /* @__PURE__ */ new Map();
|
|
239799
239899
|
getOrCreate(sessionId) {
|
|
@@ -239812,6 +239912,7 @@ var RemotePatchCache = class {
|
|
|
239812
239912
|
historyEpoch: null,
|
|
239813
239913
|
latestEntryIndex: null,
|
|
239814
239914
|
lastTurnEndEntryIndex: null,
|
|
239915
|
+
coverage: null,
|
|
239815
239916
|
sessionStatus: null
|
|
239816
239917
|
};
|
|
239817
239918
|
this.cache.set(sessionId, entry);
|
|
@@ -239860,6 +239961,7 @@ var RemotePatchCache = class {
|
|
|
239860
239961
|
if (metadata.lastTurnEnd !== null) lastTurnEndEntryIndex = Math.max(lastTurnEndEntryIndex ?? -1, metadata.lastTurnEnd);
|
|
239861
239962
|
}
|
|
239862
239963
|
const sessionStatus = existing?.sessionStatus ?? null;
|
|
239964
|
+
const coverage = existing?.coverage ?? null;
|
|
239863
239965
|
this.cache.set(sessionId, {
|
|
239864
239966
|
messages,
|
|
239865
239967
|
approxBytes: messages.reduce((sum, raw) => sum + raw.length, 0),
|
|
@@ -239873,6 +239975,7 @@ var RemotePatchCache = class {
|
|
|
239873
239975
|
historyEpoch,
|
|
239874
239976
|
latestEntryIndex,
|
|
239875
239977
|
lastTurnEndEntryIndex,
|
|
239978
|
+
coverage,
|
|
239876
239979
|
sessionStatus
|
|
239877
239980
|
});
|
|
239878
239981
|
}
|
|
@@ -239914,7 +240017,19 @@ var RemotePatchCache = class {
|
|
|
239914
240017
|
}
|
|
239915
240018
|
}
|
|
239916
240019
|
setHistoryEpoch(sessionId, epoch) {
|
|
239917
|
-
this.getOrCreate(sessionId)
|
|
240020
|
+
const entry = this.getOrCreate(sessionId);
|
|
240021
|
+
entry.historyEpoch = epoch;
|
|
240022
|
+
if (!entry.coverage) return;
|
|
240023
|
+
if (entry.coverage.epoch === null) entry.coverage.epoch = epoch;
|
|
240024
|
+
else if (entry.coverage.epoch !== epoch) entry.coverage = null;
|
|
240025
|
+
}
|
|
240026
|
+
/**
|
|
240027
|
+
* Record the interval this cache was authorized to fetch. Callers pass the
|
|
240028
|
+
* lower bound they REQUESTED upstream — 0 for an unbounded replay, N+1 for
|
|
240029
|
+
* `after=N`, the window's first index for a REST seed — not what came back.
|
|
240030
|
+
*/
|
|
240031
|
+
declareCoverage(sessionId, coverage) {
|
|
240032
|
+
this.getOrCreate(sessionId).coverage = { ...coverage };
|
|
239918
240033
|
}
|
|
239919
240034
|
/** Start a fresh entry-index namespace without dropping live connections. */
|
|
239920
240035
|
resetHistory(sessionId, epoch) {
|
|
@@ -239926,6 +240041,7 @@ var RemotePatchCache = class {
|
|
|
239926
240041
|
entry.historyEpoch = epoch;
|
|
239927
240042
|
entry.latestEntryIndex = null;
|
|
239928
240043
|
entry.lastTurnEndEntryIndex = null;
|
|
240044
|
+
entry.coverage = { epoch, start: 0 };
|
|
239929
240045
|
}
|
|
239930
240046
|
setLastTurnEndEntryIndex(sessionId, index) {
|
|
239931
240047
|
this.getOrCreate(sessionId).lastTurnEndEntryIndex = index;
|
|
@@ -240186,7 +240302,7 @@ var ReverseConnectManager = class {
|
|
|
240186
240302
|
const conn = this.connections.get(this.resolveId(remoteServerId));
|
|
240187
240303
|
return conn !== void 0 && conn.ws.readyState === 1;
|
|
240188
240304
|
}
|
|
240189
|
-
async sendHttpRequest(remoteServerId, method, path23, body, timeoutMs = DEFAULT_HTTP_TIMEOUT_MS) {
|
|
240305
|
+
async sendHttpRequest(remoteServerId, method, path23, body, timeoutMs = DEFAULT_HTTP_TIMEOUT_MS, extraHeaders) {
|
|
240190
240306
|
const conn = this.connections.get(this.resolveId(remoteServerId));
|
|
240191
240307
|
if (!conn || conn.ws.readyState !== 1) {
|
|
240192
240308
|
return {
|
|
@@ -240202,7 +240318,10 @@ var ReverseConnectManager = class {
|
|
|
240202
240318
|
requestId,
|
|
240203
240319
|
method,
|
|
240204
240320
|
path: path23,
|
|
240205
|
-
headers:
|
|
240321
|
+
headers: {
|
|
240322
|
+
...body !== void 0 ? { "content-type": "application/json" } : {},
|
|
240323
|
+
...extraHeaders
|
|
240324
|
+
},
|
|
240206
240325
|
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
240207
240326
|
};
|
|
240208
240327
|
return new Promise((resolve3) => {
|
|
@@ -240566,10 +240685,10 @@ var BrowserManager = class {
|
|
|
240566
240685
|
// src/remote-executor-monitor.ts
|
|
240567
240686
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
240568
240687
|
var RemoteExecutorMonitor = class {
|
|
240569
|
-
constructor(reverseConnectManager, eventBus,
|
|
240688
|
+
constructor(reverseConnectManager, eventBus, storage2, remoteExecutorMap) {
|
|
240570
240689
|
this.reverseConnectManager = reverseConnectManager;
|
|
240571
240690
|
this.eventBus = eventBus;
|
|
240572
|
-
this.storage =
|
|
240691
|
+
this.storage = storage2;
|
|
240573
240692
|
this.remoteExecutorMap = remoteExecutorMap;
|
|
240574
240693
|
this.reverseConnectManager.setStatusChangeHandler((_remoteServerId, status) => {
|
|
240575
240694
|
if (status !== "online") return;
|
|
@@ -240718,8 +240837,8 @@ function validateCron(expr, timezone) {
|
|
|
240718
240837
|
}
|
|
240719
240838
|
}
|
|
240720
240839
|
var SchedulerService = class {
|
|
240721
|
-
constructor(
|
|
240722
|
-
this.storage =
|
|
240840
|
+
constructor(storage2, processManager, remote) {
|
|
240841
|
+
this.storage = storage2;
|
|
240723
240842
|
this.processManager = processManager;
|
|
240724
240843
|
this.remote = remote;
|
|
240725
240844
|
}
|
|
@@ -241247,8 +241366,8 @@ function notificationTitle(kind) {
|
|
|
241247
241366
|
return TITLE_BY_KIND[kind] ?? "Update";
|
|
241248
241367
|
}
|
|
241249
241368
|
var NotificationService = class {
|
|
241250
|
-
constructor(
|
|
241251
|
-
this.storage =
|
|
241369
|
+
constructor(storage2, eventBus) {
|
|
241370
|
+
this.storage = storage2;
|
|
241252
241371
|
this.eventBus = eventBus;
|
|
241253
241372
|
}
|
|
241254
241373
|
storage;
|
|
@@ -241403,18 +241522,18 @@ var emptyReasons = () => ({
|
|
|
241403
241522
|
dangling_checkout: 0,
|
|
241404
241523
|
snapshot_mismatch: 0
|
|
241405
241524
|
});
|
|
241406
|
-
async function registerReportedWorktrees(
|
|
241525
|
+
async function registerReportedWorktrees(storage2, opts) {
|
|
241407
241526
|
for (const worktree of opts.worktrees) {
|
|
241408
241527
|
const branch = worktree.branch ?? "";
|
|
241409
241528
|
const fallbackPath = branch ? conventionalWorktreePath(opts.remotePath, branch) : opts.remotePath;
|
|
241410
241529
|
const reportedPath = typeof worktree.worktreePath === "string" ? worktree.worktreePath : null;
|
|
241411
|
-
const existing = await
|
|
241530
|
+
const existing = await storage2.workspaceRegistry.getByProjectBranch(
|
|
241412
241531
|
opts.projectId,
|
|
241413
241532
|
branch,
|
|
241414
241533
|
opts.targetId
|
|
241415
241534
|
);
|
|
241416
241535
|
if (existing && (!reportedPath || existing.checkout.path_source === "reported" && existing.checkout.worktree_path === reportedPath)) continue;
|
|
241417
|
-
await
|
|
241536
|
+
await storage2.workspaceRegistry.registerReadyCheckout({
|
|
241418
241537
|
projectId: opts.projectId,
|
|
241419
241538
|
branch,
|
|
241420
241539
|
targetId: opts.targetId,
|
|
@@ -241424,20 +241543,20 @@ async function registerReportedWorktrees(storage, opts) {
|
|
|
241424
241543
|
});
|
|
241425
241544
|
}
|
|
241426
241545
|
}
|
|
241427
|
-
async function syncLocalWorkspaceRegistry(
|
|
241428
|
-
const projects = await
|
|
241546
|
+
async function syncLocalWorkspaceRegistry(storage2) {
|
|
241547
|
+
const projects = await storage2.workspaceBindingMigration.listUnboundLocalProjects();
|
|
241429
241548
|
for (const project of projects) {
|
|
241430
241549
|
try {
|
|
241431
|
-
await getRegisteredWorktreeBranches(
|
|
241550
|
+
await getRegisteredWorktreeBranches(storage2, project.id, project.path);
|
|
241432
241551
|
} catch (error48) {
|
|
241433
241552
|
console.warn(`[WorkspaceBinding] Local registry sync failed for ${project.id}:`, error48);
|
|
241434
241553
|
}
|
|
241435
241554
|
}
|
|
241436
241555
|
}
|
|
241437
|
-
async function syncRemoteWorkspaceRegistry(
|
|
241438
|
-
const projects = await
|
|
241556
|
+
async function syncRemoteWorkspaceRegistry(storage2, listWorktrees, opts = {}) {
|
|
241557
|
+
const projects = await storage2.projects.getAll();
|
|
241439
241558
|
for (const project of projects) {
|
|
241440
|
-
const remotes = await
|
|
241559
|
+
const remotes = await storage2.projectRemotes.getByProject(project.id);
|
|
241441
241560
|
for (const remote of remotes) {
|
|
241442
241561
|
if (opts.remoteServerId && remote.remote_server_id !== opts.remoteServerId) continue;
|
|
241443
241562
|
try {
|
|
@@ -241445,7 +241564,7 @@ async function syncRemoteWorkspaceRegistry(storage, listWorktrees, opts = {}) {
|
|
|
241445
241564
|
if (!result.ok) continue;
|
|
241446
241565
|
const worktrees = result.data?.worktrees;
|
|
241447
241566
|
if (!Array.isArray(worktrees)) continue;
|
|
241448
|
-
await registerReportedWorktrees(
|
|
241567
|
+
await registerReportedWorktrees(storage2, {
|
|
241449
241568
|
projectId: project.id,
|
|
241450
241569
|
targetId: remote.remote_server_id,
|
|
241451
241570
|
remotePath: remote.remote_path,
|
|
@@ -241460,7 +241579,7 @@ async function syncRemoteWorkspaceRegistry(storage, listWorktrees, opts = {}) {
|
|
|
241460
241579
|
}
|
|
241461
241580
|
}
|
|
241462
241581
|
}
|
|
241463
|
-
async function runWorkspaceBindingBackfill(
|
|
241582
|
+
async function runWorkspaceBindingBackfill(storage2, kind, opts = {}) {
|
|
241464
241583
|
const now3 = opts.now ?? Date.now;
|
|
241465
241584
|
const deadline = now3() + (opts.budgetMs ?? DEFAULT_BUDGET_MS);
|
|
241466
241585
|
const summary = {
|
|
@@ -241471,7 +241590,7 @@ async function runWorkspaceBindingBackfill(storage, kind, opts = {}) {
|
|
|
241471
241590
|
};
|
|
241472
241591
|
let cursor = "";
|
|
241473
241592
|
for (; ; ) {
|
|
241474
|
-
const batch = await
|
|
241593
|
+
const batch = await storage2.workspaceBindingMigration.backfill({
|
|
241475
241594
|
kind,
|
|
241476
241595
|
dryRun: false,
|
|
241477
241596
|
batchSize: opts.batchSize ?? DEFAULT_BATCH_SIZE,
|
|
@@ -241490,22 +241609,22 @@ async function runWorkspaceBindingBackfill(storage, kind, opts = {}) {
|
|
|
241490
241609
|
}
|
|
241491
241610
|
}
|
|
241492
241611
|
}
|
|
241493
|
-
async function healWorkspaceBindings(
|
|
241494
|
-
const probes = await Promise.all(["local", "remote"].map((kind) =>
|
|
241612
|
+
async function healWorkspaceBindings(storage2, deps = {}, opts = {}) {
|
|
241613
|
+
const probes = await Promise.all(["local", "remote"].map((kind) => storage2.workspaceBindingMigration.backfill({ kind, dryRun: true, batchSize: 1 })));
|
|
241495
241614
|
if (probes.every((probe) => probe.scanned === 0)) {
|
|
241496
241615
|
return {
|
|
241497
241616
|
local: { scanned: 0, updated: 0, reasons: emptyReasons(), incomplete: false },
|
|
241498
241617
|
remote: { scanned: 0, updated: 0, reasons: emptyReasons(), incomplete: false }
|
|
241499
241618
|
};
|
|
241500
241619
|
}
|
|
241501
|
-
if (!opts.remoteServerId) await syncLocalWorkspaceRegistry(
|
|
241620
|
+
if (!opts.remoteServerId) await syncLocalWorkspaceRegistry(storage2);
|
|
241502
241621
|
if (deps.listRemoteWorktrees) {
|
|
241503
|
-
await syncRemoteWorkspaceRegistry(
|
|
241622
|
+
await syncRemoteWorkspaceRegistry(storage2, deps.listRemoteWorktrees, {
|
|
241504
241623
|
remoteServerId: opts.remoteServerId
|
|
241505
241624
|
});
|
|
241506
241625
|
}
|
|
241507
|
-
const local = opts.remoteServerId ? { scanned: 0, updated: 0, reasons: emptyReasons(), incomplete: false } : await runWorkspaceBindingBackfill(
|
|
241508
|
-
const remote = await runWorkspaceBindingBackfill(
|
|
241626
|
+
const local = opts.remoteServerId ? { scanned: 0, updated: 0, reasons: emptyReasons(), incomplete: false } : await runWorkspaceBindingBackfill(storage2, "local", opts);
|
|
241627
|
+
const remote = await runWorkspaceBindingBackfill(storage2, "remote", opts);
|
|
241509
241628
|
return { local, remote };
|
|
241510
241629
|
}
|
|
241511
241630
|
function formatBackfillSummary(scope, result) {
|
|
@@ -241536,8 +241655,8 @@ function parseRetentionDays(raw) {
|
|
|
241536
241655
|
if (value < SESSION_RETENTION_DAYS_MIN || value > SESSION_RETENTION_DAYS_MAX) return null;
|
|
241537
241656
|
return value;
|
|
241538
241657
|
}
|
|
241539
|
-
async function readRetentionDays(
|
|
241540
|
-
return parseRetentionDays(await
|
|
241658
|
+
async function readRetentionDays(storage2) {
|
|
241659
|
+
return parseRetentionDays(await storage2.settings.get(SESSION_RETENTION_SETTING_KEY));
|
|
241541
241660
|
}
|
|
241542
241661
|
function retentionCutoff(days, now3) {
|
|
241543
241662
|
return now3 - days * MS_PER_DAY;
|
|
@@ -241713,12 +241832,12 @@ var DEFAULT_DEADLINE_MS = 5e3;
|
|
|
241713
241832
|
var PER_WORKER_CONCURRENCY = 3;
|
|
241714
241833
|
var LOCAL_CONCURRENCY = 4;
|
|
241715
241834
|
var REMOTE_ACTIVITY_TARGET_LIMIT = 100;
|
|
241716
|
-
async function listSearchTargets(
|
|
241717
|
-
const projects = await
|
|
241835
|
+
async function listSearchTargets(storage2, userId) {
|
|
241836
|
+
const projects = await storage2.projects.getAll(userId);
|
|
241718
241837
|
const targets = [];
|
|
241719
241838
|
for (const p2 of projects) {
|
|
241720
241839
|
if (p2.path) targets.push({ projectId: p2.id, targetId: "local", projectPath: p2.path });
|
|
241721
|
-
const remotes = await
|
|
241840
|
+
const remotes = await storage2.projectRemotes.getByProject(p2.id);
|
|
241722
241841
|
for (const r of remotes) {
|
|
241723
241842
|
targets.push({
|
|
241724
241843
|
projectId: p2.id,
|
|
@@ -242582,11 +242701,21 @@ function resolveLevel(flagLevel) {
|
|
|
242582
242701
|
console.warn(`Warning: invalid log level "${requested}" (valid: ${[...VALID_LEVELS].join(", ")}); using "info"`);
|
|
242583
242702
|
return "info";
|
|
242584
242703
|
}
|
|
242704
|
+
var traceLoggers = /* @__PURE__ */ new WeakMap();
|
|
242705
|
+
function withTraceContext(base) {
|
|
242706
|
+
const ctx = getTraceContext();
|
|
242707
|
+
if (!ctx) return base;
|
|
242708
|
+
const cached2 = traceLoggers.get(ctx);
|
|
242709
|
+
if (cached2 && cached2.base === base) return cached2.child;
|
|
242710
|
+
const child = base.child({ traceId: ctx.traceId, spanId: ctx.spanId });
|
|
242711
|
+
traceLoggers.set(ctx, { base, child });
|
|
242712
|
+
return child;
|
|
242713
|
+
}
|
|
242585
242714
|
function getLogger() {
|
|
242586
242715
|
if (!rootLogger) {
|
|
242587
242716
|
rootLogger = (0, import_pino.pino)({ level: resolveLevel(void 0) });
|
|
242588
242717
|
}
|
|
242589
|
-
return rootLogger;
|
|
242718
|
+
return withTraceContext(rootLogger);
|
|
242590
242719
|
}
|
|
242591
242720
|
function setupLogging(opts) {
|
|
242592
242721
|
const level = resolveLevel(opts.level);
|
|
@@ -242649,11 +242778,11 @@ function installConsoleBridge(logger) {
|
|
|
242649
242778
|
debug: console.debug
|
|
242650
242779
|
};
|
|
242651
242780
|
}
|
|
242652
|
-
console.log = (...args) => logger.info(format(...args));
|
|
242653
|
-
console.info = (...args) => logger.info(format(...args));
|
|
242654
|
-
console.warn = (...args) => logger.warn(format(...args));
|
|
242655
|
-
console.error = (...args) => logger.error(format(...args));
|
|
242656
|
-
console.debug = (...args) => logger.debug(format(...args));
|
|
242781
|
+
console.log = (...args) => withTraceContext(logger).info(format(...args));
|
|
242782
|
+
console.info = (...args) => withTraceContext(logger).info(format(...args));
|
|
242783
|
+
console.warn = (...args) => withTraceContext(logger).warn(format(...args));
|
|
242784
|
+
console.error = (...args) => withTraceContext(logger).error(format(...args));
|
|
242785
|
+
console.debug = (...args) => withTraceContext(logger).debug(format(...args));
|
|
242657
242786
|
}
|
|
242658
242787
|
function installCrashHandlers(logger) {
|
|
242659
242788
|
if (crashHandlersInstalled) return;
|
|
@@ -246798,12 +246927,12 @@ function writeBriefCache(key2, brief) {
|
|
|
246798
246927
|
briefCache.delete(oldest.value);
|
|
246799
246928
|
}
|
|
246800
246929
|
}
|
|
246801
|
-
async function generateIntentBrief(
|
|
246930
|
+
async function generateIntentBrief(storage2, userId, messages) {
|
|
246802
246931
|
let conversation;
|
|
246803
246932
|
let mainOk;
|
|
246804
246933
|
let fastOk;
|
|
246805
246934
|
try {
|
|
246806
|
-
const config2 = await getChatProviderConfig(
|
|
246935
|
+
const config2 = await getChatProviderConfig(storage2, userId);
|
|
246807
246936
|
mainOk = isModelConfigured(config2, config2.main);
|
|
246808
246937
|
fastOk = isModelConfigured(config2, config2.fast);
|
|
246809
246938
|
if (!mainOk && !fastOk) return null;
|
|
@@ -246818,17 +246947,17 @@ async function generateIntentBrief(storage, userId, messages) {
|
|
|
246818
246947
|
if (cached2 !== null) return cached2;
|
|
246819
246948
|
const pending = briefInFlight.get(key2);
|
|
246820
246949
|
if (pending) return pending;
|
|
246821
|
-
const run2 = distillConversation(
|
|
246950
|
+
const run2 = distillConversation(storage2, userId, messages, conversation, mainOk, fastOk).then((brief) => {
|
|
246822
246951
|
if (brief !== null) writeBriefCache(key2, brief);
|
|
246823
246952
|
return brief;
|
|
246824
246953
|
}).finally(() => briefInFlight.delete(key2));
|
|
246825
246954
|
briefInFlight.set(key2, run2);
|
|
246826
246955
|
return run2;
|
|
246827
246956
|
}
|
|
246828
|
-
async function distillConversation(
|
|
246957
|
+
async function distillConversation(storage2, userId, messages, conversation, mainOk, fastOk) {
|
|
246829
246958
|
try {
|
|
246830
|
-
const distillModel = mainOk ? await resolveChatModel(
|
|
246831
|
-
const compactModel = fastOk ? await resolveFastChatModel(
|
|
246959
|
+
const distillModel = mainOk ? await resolveChatModel(storage2, userId) : await resolveFastChatModel(storage2, userId);
|
|
246960
|
+
const compactModel = fastOk ? await resolveFastChatModel(storage2, userId) : distillModel;
|
|
246832
246961
|
if (conversation.length <= COMPACT_TRIGGER_CHARS) {
|
|
246833
246962
|
try {
|
|
246834
246963
|
const brief = await distill(distillModel, conversation, userId, true);
|
|
@@ -246906,11 +247035,11 @@ function buildHistoryWindow(entries, historyEpoch, opts = {}) {
|
|
|
246906
247035
|
}
|
|
246907
247036
|
|
|
246908
247037
|
// src/routes/agent-session-routes.ts
|
|
246909
|
-
async function resolveProjectPath(projectId,
|
|
247038
|
+
async function resolveProjectPath(projectId, storage2) {
|
|
246910
247039
|
if (projectId.startsWith("path:")) {
|
|
246911
247040
|
return projectId.slice(5);
|
|
246912
247041
|
}
|
|
246913
|
-
const project = await
|
|
247042
|
+
const project = await storage2.projects.getById(projectId);
|
|
246914
247043
|
return project?.path ?? null;
|
|
246915
247044
|
}
|
|
246916
247045
|
var MESSAGE_TEXT_CHAR_LIMIT = 64 * 1024;
|
|
@@ -247594,6 +247723,10 @@ var routes11 = async (fastify2) => {
|
|
|
247594
247723
|
const patch = ConversationPatch.addEntry(entryIndex, message);
|
|
247595
247724
|
fastify2.remotePatchCache.appendMessage(localSessionId, JSON.stringify({ JsonPatch: patch }), true);
|
|
247596
247725
|
}
|
|
247726
|
+
fastify2.remotePatchCache.declareCoverage(localSessionId, {
|
|
247727
|
+
epoch: remoteData.historyWindow?.historyEpoch ?? null,
|
|
247728
|
+
start: seededEntries[0]?.entryIndex ?? 0
|
|
247729
|
+
});
|
|
247597
247730
|
if (remoteData.historyWindow) {
|
|
247598
247731
|
fastify2.remotePatchCache.setHistoryEpoch(localSessionId, remoteData.historyWindow.historyEpoch);
|
|
247599
247732
|
if (remoteData.historyWindow.lastTurnEndEntryIndex !== null) {
|
|
@@ -247862,6 +247995,9 @@ var routes11 = async (fastify2) => {
|
|
|
247862
247995
|
);
|
|
247863
247996
|
if (result.ok) {
|
|
247864
247997
|
const data = result.data;
|
|
247998
|
+
console.log(
|
|
247999
|
+
`[API] history-window ${req.params.sessionId}: latest=${String(data.latestEntryIndex)}, lastTurnEnd=${String(data.lastTurnEndEntryIndex)}, hasMore=${String(data.hasMore)}, before=${before ?? "-"}, turns=${turns}`
|
|
248000
|
+
);
|
|
247865
248001
|
return reply.code(200).send({
|
|
247866
248002
|
...data,
|
|
247867
248003
|
session: data.session ? {
|
|
@@ -247917,6 +248053,9 @@ var routes11 = async (fastify2) => {
|
|
|
247917
248053
|
if (!remoteInfo) return reply.code(404).send({ error: "Remote session not found" });
|
|
247918
248054
|
const cached2 = fastify2.remotePatchCache.get(req.params.sessionId);
|
|
247919
248055
|
if (cached2?.historyEpoch !== null && cached2?.lastTurnEndEntryIndex !== null && cached2?.sessionStatus) {
|
|
248056
|
+
console.log(
|
|
248057
|
+
`[API] history-head ${req.params.sessionId} (from cache): latest=${cached2.latestEntryIndex}, lastTurnEnd=${cached2.lastTurnEndEntryIndex}, status=${cached2.sessionStatus}`
|
|
248058
|
+
);
|
|
247920
248059
|
return reply.code(200).send({
|
|
247921
248060
|
historyEpoch: cached2.historyEpoch,
|
|
247922
248061
|
latestEntryIndex: cached2.latestEntryIndex,
|
|
@@ -247929,7 +248068,13 @@ var routes11 = async (fastify2) => {
|
|
|
247929
248068
|
"GET",
|
|
247930
248069
|
`/api/agent-sessions/${encodeURIComponent(remoteInfo.remoteSessionId)}/history-head`
|
|
247931
248070
|
);
|
|
247932
|
-
if (result.ok)
|
|
248071
|
+
if (result.ok) {
|
|
248072
|
+
const head3 = result.data;
|
|
248073
|
+
console.log(
|
|
248074
|
+
`[API] history-head ${req.params.sessionId} (from worker): latest=${String(head3.latestEntryIndex)}, lastTurnEnd=${String(head3.lastTurnEndEntryIndex)}, status=${String(head3.status)}`
|
|
248075
|
+
);
|
|
248076
|
+
return reply.code(200).send(result.data);
|
|
248077
|
+
}
|
|
247933
248078
|
if (result.status !== 404) return reply.code(proxyStatus(result)).send(result.data);
|
|
247934
248079
|
const legacy = await proxyAuto(
|
|
247935
248080
|
remoteInfo.remoteServerId,
|
|
@@ -249461,7 +249606,7 @@ var mergeActivity = (local, remote, limit) => {
|
|
|
249461
249606
|
for (const row of [...local, ...remote]) if (!byId.has(row.id)) byId.set(row.id, row);
|
|
249462
249607
|
return [...byId.values()].sort((left, right) => (right.lastActiveAt ?? 0) - (left.lastActiveAt ?? 0) || left.id.localeCompare(right.id)).slice(0, limit);
|
|
249463
249608
|
};
|
|
249464
|
-
async function getProjectActivity(
|
|
249609
|
+
async function getProjectActivity(storage2, projectId, userId) {
|
|
249465
249610
|
const [
|
|
249466
249611
|
recentThreads,
|
|
249467
249612
|
localRecentSessions,
|
|
@@ -249476,18 +249621,18 @@ async function getProjectActivity(storage, projectId, userId) {
|
|
|
249476
249621
|
remoteCounts,
|
|
249477
249622
|
nextScheduleAt
|
|
249478
249623
|
] = await Promise.all([
|
|
249479
|
-
|
|
249480
|
-
|
|
249481
|
-
|
|
249482
|
-
|
|
249483
|
-
|
|
249484
|
-
|
|
249485
|
-
|
|
249486
|
-
|
|
249487
|
-
|
|
249488
|
-
|
|
249489
|
-
|
|
249490
|
-
|
|
249624
|
+
storage2.projectChatThreads.listByProject(projectId, userId, RECENT_THREAD_LIMIT),
|
|
249625
|
+
storage2.agentSessions.listRecentActivityByProject(projectId, RECENT_SESSION_LIMIT, "project-activity"),
|
|
249626
|
+
storage2.searchCache.listRemoteSessionActivityByProject(projectId, RECENT_SESSION_LIMIT, "project-activity"),
|
|
249627
|
+
storage2.scheduledTaskRuns.getRecentByProject(projectId, RECENT_RUN_LIMIT),
|
|
249628
|
+
storage2.tasks.listPriorityByProject(projectId, PRIORITY_TASK_LIMIT),
|
|
249629
|
+
storage2.agentSessions.listAttentionActivityByProject(projectId, ATTENTION_LIMIT, "project-activity"),
|
|
249630
|
+
storage2.searchCache.listRemoteSessionAttentionByProject(projectId, ATTENTION_LIMIT, "project-activity"),
|
|
249631
|
+
storage2.scheduledTaskRuns.getAttentionByProject(projectId, ATTENTION_LIMIT),
|
|
249632
|
+
storage2.agentSessions.countRunningActivityByProject(projectId),
|
|
249633
|
+
storage2.scheduledTaskRuns.countByProjectStatuses(projectId, ["starting", "running"]),
|
|
249634
|
+
storage2.searchCache.countRemoteSessionActivityByProject(projectId),
|
|
249635
|
+
storage2.scheduledTasks.getEarliestNextRunAt(projectId)
|
|
249491
249636
|
]);
|
|
249492
249637
|
const recentAgentSessions = mergeActivity(
|
|
249493
249638
|
localRecentSessions,
|
|
@@ -251502,6 +251647,11 @@ var routes23 = async (fastify2) => {
|
|
|
251502
251647
|
afterEntryIndex
|
|
251503
251648
|
);
|
|
251504
251649
|
console.log(`[AgentWS] Replaying cached msgs for ${sessionId} after=${replayAfter}`);
|
|
251650
|
+
if (!coverageAdmitsReplay(cacheEntry.coverage, historyEpoch, afterEntryIndex)) {
|
|
251651
|
+
console.warn(
|
|
251652
|
+
`[AgentWS] COVERAGE GAP ${sessionId}: client needs from ${(afterEntryIndex ?? -1) + 1} (epoch=${historyEpoch ?? "-"}), cache covers from ${cacheEntry.coverage?.start ?? "unknown"} (epoch=${cacheEntry.coverage?.epoch ?? "-"}), frames=${cacheEntry.messages.length}, entriesLatest=${cacheEntry.latestEntryIndex ?? "-"} \u2014 Ready will be sent anyway`
|
|
251653
|
+
);
|
|
251654
|
+
}
|
|
251505
251655
|
try {
|
|
251506
251656
|
socket.send(JSON.stringify({
|
|
251507
251657
|
HistorySync: {
|
|
@@ -251701,7 +251851,7 @@ var websocket_routes_default = (0, import_fastify_plugin24.default)(routes23, {
|
|
|
251701
251851
|
|
|
251702
251852
|
// src/routes/reverse-connect-routes.ts
|
|
251703
251853
|
var import_fastify_plugin25 = __toESM(require_plugin2(), 1);
|
|
251704
|
-
import { randomBytes as
|
|
251854
|
+
import { randomBytes as randomBytes4, createHash as createHash8, verify as cryptoVerify } from "crypto";
|
|
251705
251855
|
|
|
251706
251856
|
// src/utils/rate-limited-warn.ts
|
|
251707
251857
|
function createRateLimitedWarn(windowMs, maxKeys) {
|
|
@@ -251784,7 +251934,7 @@ var routes24 = async (fastify2) => {
|
|
|
251784
251934
|
const ws = socket;
|
|
251785
251935
|
const serverId = server.id;
|
|
251786
251936
|
const ownerId = await fastify2.storage.remoteServers.getOwnerId(serverId) ?? "";
|
|
251787
|
-
const nonce =
|
|
251937
|
+
const nonce = randomBytes4(32);
|
|
251788
251938
|
let settled = false;
|
|
251789
251939
|
let stashedVersion;
|
|
251790
251940
|
const recordWorkerVersion = async (reported) => {
|
|
@@ -253352,7 +253502,8 @@ var routes31 = async (fastify2) => {
|
|
|
253352
253502
|
return respond({
|
|
253353
253503
|
protocolVersion: PROTOCOL_VERSION2,
|
|
253354
253504
|
capabilities: { tools: {} },
|
|
253355
|
-
serverInfo: { name: "vibedeckx-session-tools", version: "1.0.0" }
|
|
253505
|
+
serverInfo: { name: "vibedeckx-session-tools", version: "1.0.0" },
|
|
253506
|
+
instructions: SESSION_TOOLS_MCP_INSTRUCTIONS
|
|
253356
253507
|
});
|
|
253357
253508
|
case "ping":
|
|
253358
253509
|
return respond({});
|
|
@@ -254244,6 +254395,43 @@ var getAuth = ((req, options) => {
|
|
|
254244
254395
|
return getAuthObjectForAcceptedToken({ authObject: authReq.auth, acceptsToken: options?.acceptsToken });
|
|
254245
254396
|
});
|
|
254246
254397
|
|
|
254398
|
+
// src/trace-context-hooks.ts
|
|
254399
|
+
function registerTraceContext(server) {
|
|
254400
|
+
server.addHook("onRequest", (req, _reply, done) => {
|
|
254401
|
+
const ctx = newTraceContext(req.headers["traceparent"]);
|
|
254402
|
+
req.traceContext = ctx;
|
|
254403
|
+
req.traceStartMs = Date.now();
|
|
254404
|
+
runWithTraceContext(ctx, done);
|
|
254405
|
+
});
|
|
254406
|
+
server.addHook("onSend", (req, reply, payload, done) => {
|
|
254407
|
+
if (req.traceContext) {
|
|
254408
|
+
reply.header("traceparent", formatTraceparent(req.traceContext));
|
|
254409
|
+
}
|
|
254410
|
+
done(null, payload);
|
|
254411
|
+
});
|
|
254412
|
+
server.addHook("onResponse", (req, reply, done) => {
|
|
254413
|
+
const ctx = req.traceContext;
|
|
254414
|
+
if (ctx) {
|
|
254415
|
+
const status = reply.statusCode;
|
|
254416
|
+
const level = status >= 500 ? "error" : status >= 400 ? "warn" : "debug";
|
|
254417
|
+
getLogger()[level](
|
|
254418
|
+
{
|
|
254419
|
+
method: req.method,
|
|
254420
|
+
// The route *pattern* (/api/projects/:id), not the concrete URL:
|
|
254421
|
+
// low-cardinality and structurally incapable of carrying the query
|
|
254422
|
+
// string, where WebSocket/SSE auth material rides.
|
|
254423
|
+
route: req.routeOptions?.url,
|
|
254424
|
+
statusCode: status,
|
|
254425
|
+
ms: req.traceStartMs ? Date.now() - req.traceStartMs : void 0,
|
|
254426
|
+
continuedTrace: ctx.continued
|
|
254427
|
+
},
|
|
254428
|
+
"request completed"
|
|
254429
|
+
);
|
|
254430
|
+
}
|
|
254431
|
+
done();
|
|
254432
|
+
});
|
|
254433
|
+
}
|
|
254434
|
+
|
|
254247
254435
|
// src/server.ts
|
|
254248
254436
|
var API_KEY2 = process.env.VIBEDECKX_API_KEY || void 0;
|
|
254249
254437
|
function requireAuth(req, reply) {
|
|
@@ -254322,10 +254510,12 @@ var createServer = async (opts) => {
|
|
|
254322
254510
|
});
|
|
254323
254511
|
server.decorate("authEnabled", authEnabled);
|
|
254324
254512
|
server.decorate("noLocalProjects", noLocalProjects);
|
|
254513
|
+
registerTraceContext(server);
|
|
254325
254514
|
server.addHook("onRequest", (req, reply, done) => {
|
|
254326
254515
|
reply.header("access-control-allow-origin", "*");
|
|
254327
254516
|
reply.header("access-control-allow-methods", "GET, POST, PUT, DELETE, OPTIONS");
|
|
254328
|
-
reply.header("access-control-allow-headers", "Content-Type, Upgrade, Connection, X-Vibedeckx-Api-Key, X-Request-Id, Authorization");
|
|
254517
|
+
reply.header("access-control-allow-headers", "Content-Type, Upgrade, Connection, X-Vibedeckx-Api-Key, X-Request-Id, Authorization, traceparent");
|
|
254518
|
+
reply.header("access-control-expose-headers", "traceparent");
|
|
254329
254519
|
done();
|
|
254330
254520
|
});
|
|
254331
254521
|
server.addHook("onRequest", (req, reply, done) => {
|
|
@@ -254353,23 +254543,6 @@ var createServer = async (opts) => {
|
|
|
254353
254543
|
done();
|
|
254354
254544
|
});
|
|
254355
254545
|
}
|
|
254356
|
-
server.addHook("onRequest", (req, _reply, done) => {
|
|
254357
|
-
const requestId = req.headers["x-request-id"];
|
|
254358
|
-
if (requestId) {
|
|
254359
|
-
req.startTime = Date.now();
|
|
254360
|
-
console.log(`[remote] ${requestId} ${req.method} ${redactUrlForLog(req.url)}`);
|
|
254361
|
-
}
|
|
254362
|
-
done();
|
|
254363
|
-
});
|
|
254364
|
-
server.addHook("onResponse", (req, reply, done) => {
|
|
254365
|
-
const requestId = req.headers["x-request-id"];
|
|
254366
|
-
if (requestId) {
|
|
254367
|
-
const startTime = req.startTime;
|
|
254368
|
-
const ms = startTime ? Date.now() - startTime : 0;
|
|
254369
|
-
console.log(`[remote] ${requestId} ${req.method} ${redactUrlForLog(req.url)} -> ${reply.statusCode} (${ms}ms)`);
|
|
254370
|
-
}
|
|
254371
|
-
done();
|
|
254372
|
-
});
|
|
254373
254546
|
server.options("/*", async (req, reply) => {
|
|
254374
254547
|
return reply.code(204).send();
|
|
254375
254548
|
});
|
|
@@ -256570,8 +256743,8 @@ an authenticating proxy in front, or keep the default loopback bind (127.0.0.1).
|
|
|
256570
256743
|
console.log(`Starting vibedeckx${tls ? " (HTTPS)" : ""}...`);
|
|
256571
256744
|
const uiRoot = await resolveUiRoot({ uiDir: flags["ui-dir"], noUi: flags["no-ui"] });
|
|
256572
256745
|
const dbPath = path22.join(dataDir, "data.sqlite");
|
|
256573
|
-
const
|
|
256574
|
-
const server = await createServer({ storage, authEnabled, noLocalProjects, tls, uiRoot });
|
|
256746
|
+
const storage2 = await createSqliteStorage(dbPath);
|
|
256747
|
+
const server = await createServer({ storage: storage2, authEnabled, noLocalProjects, tls, uiRoot });
|
|
256575
256748
|
const url2 = await server.start(port, host);
|
|
256576
256749
|
console.log(`Server running at ${url2}`);
|
|
256577
256750
|
if (!tls && uiRoot) {
|
|
@@ -256592,7 +256765,7 @@ an authenticating proxy in front, or keep the default loopback bind (127.0.0.1).
|
|
|
256592
256765
|
forceExit.unref();
|
|
256593
256766
|
try {
|
|
256594
256767
|
await server.close();
|
|
256595
|
-
await
|
|
256768
|
+
await storage2.close();
|
|
256596
256769
|
} catch (err) {
|
|
256597
256770
|
console.error("Error during shutdown:", err);
|
|
256598
256771
|
}
|
|
@@ -256676,7 +256849,7 @@ var connectCommand = buildCommand({
|
|
|
256676
256849
|
return;
|
|
256677
256850
|
}
|
|
256678
256851
|
const requestedPort = flags.port ?? 0;
|
|
256679
|
-
let
|
|
256852
|
+
let storage2;
|
|
256680
256853
|
let server;
|
|
256681
256854
|
let client;
|
|
256682
256855
|
let ownedState;
|
|
@@ -256698,7 +256871,7 @@ var connectCommand = buildCommand({
|
|
|
256698
256871
|
errors.push(error48);
|
|
256699
256872
|
}
|
|
256700
256873
|
try {
|
|
256701
|
-
await
|
|
256874
|
+
await storage2?.close();
|
|
256702
256875
|
} catch (error48) {
|
|
256703
256876
|
errors.push(error48);
|
|
256704
256877
|
}
|
|
@@ -256729,11 +256902,11 @@ var connectCommand = buildCommand({
|
|
|
256729
256902
|
});
|
|
256730
256903
|
console.log("Starting vibedeckx in reverse-connect mode...");
|
|
256731
256904
|
const dbPath = path22.join(dataDir, "data.sqlite");
|
|
256732
|
-
|
|
256905
|
+
storage2 = await createSqliteStorage(dbPath);
|
|
256733
256906
|
const preflight = await preflightIdentityCheck({
|
|
256734
256907
|
connectTo: flags["connect-to"],
|
|
256735
256908
|
token,
|
|
256736
|
-
settings:
|
|
256909
|
+
settings: storage2.settings,
|
|
256737
256910
|
force: flags.force ?? false
|
|
256738
256911
|
});
|
|
256739
256912
|
if (preflight.checked && preflight.identity) {
|
|
@@ -256742,7 +256915,7 @@ var connectCommand = buildCommand({
|
|
|
256742
256915
|
);
|
|
256743
256916
|
}
|
|
256744
256917
|
server = await createServer({
|
|
256745
|
-
storage,
|
|
256918
|
+
storage: storage2,
|
|
256746
256919
|
acceptRemote: true,
|
|
256747
256920
|
uiRoot: null
|
|
256748
256921
|
});
|