ai-browser-bridge 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -10
- package/dist/bridge.js +562 -103
- package/dist/bridge.js.map +1 -1
- package/package.json +1 -1
package/dist/bridge.js
CHANGED
|
@@ -11150,7 +11150,7 @@ var serveAskGatewayStdio = async (deps) => {
|
|
|
11150
11150
|
// src/features/terminal/chatOrganizationQueue.ts
|
|
11151
11151
|
import { createHash as createHash2, randomUUID as randomUUID4 } from "crypto";
|
|
11152
11152
|
import { existsSync } from "fs";
|
|
11153
|
-
import { mkdir as mkdir7, open, readFile as readFile10, rename, unlink, writeFile as writeFile5 } from "fs/promises";
|
|
11153
|
+
import { mkdir as mkdir7, open, readdir as readdir5, readFile as readFile10, rename, unlink, writeFile as writeFile5 } from "fs/promises";
|
|
11154
11154
|
import { dirname as dirname3, isAbsolute, join as join11, resolve as resolve7 } from "path";
|
|
11155
11155
|
import { Schema as Schema8 } from "effect";
|
|
11156
11156
|
var ChatOrganizationTaskSchema = Schema8.Struct({
|
|
@@ -11187,12 +11187,27 @@ var ChatOrganizationQueueItemSchema = Schema8.Union(
|
|
|
11187
11187
|
CompletedQueueItemSchema,
|
|
11188
11188
|
FailedQueueItemSchema
|
|
11189
11189
|
);
|
|
11190
|
+
var ChatOrganizationPacingSchema = Schema8.Struct({
|
|
11191
|
+
currentSeconds: Schema8.Number.pipe(Schema8.int(), Schema8.positive()),
|
|
11192
|
+
successStreak: Schema8.Number.pipe(Schema8.int(), Schema8.nonNegative()),
|
|
11193
|
+
rateLimitCount: Schema8.Number.pipe(Schema8.int(), Schema8.nonNegative())
|
|
11194
|
+
});
|
|
11195
|
+
var ChatOrganizationVerificationSchema = Schema8.Struct({
|
|
11196
|
+
complete: Schema8.Boolean,
|
|
11197
|
+
inventoryComplete: Schema8.Boolean,
|
|
11198
|
+
remainingOrphans: Schema8.Number.pipe(Schema8.int(), Schema8.nonNegative()),
|
|
11199
|
+
plannedStillLoose: Schema8.Array(Schema8.String),
|
|
11200
|
+
verifiedAt: Schema8.String,
|
|
11201
|
+
error: Schema8.optional(Schema8.String)
|
|
11202
|
+
});
|
|
11190
11203
|
var ChatOrganizationQueueSchema = Schema8.Struct({
|
|
11191
11204
|
version: Schema8.Literal(1),
|
|
11192
11205
|
fingerprint: Schema8.String,
|
|
11193
11206
|
createdAt: Schema8.String,
|
|
11194
11207
|
updatedAt: Schema8.String,
|
|
11195
|
-
items: Schema8.Array(ChatOrganizationQueueItemSchema).pipe(Schema8.minItems(1))
|
|
11208
|
+
items: Schema8.Array(ChatOrganizationQueueItemSchema).pipe(Schema8.minItems(1)),
|
|
11209
|
+
pacing: Schema8.optional(ChatOrganizationPacingSchema),
|
|
11210
|
+
verification: Schema8.optional(ChatOrganizationVerificationSchema)
|
|
11196
11211
|
});
|
|
11197
11212
|
var ORGANIZATION_INTERVAL = /^(?<minimum>\d+)(?:-(?<maximum>\d+))?$/u;
|
|
11198
11213
|
var CLOSED_BROWSER_SESSION = /(?:target page, context or browser has been closed|browser has been closed|context has been closed|page has been closed)/iu;
|
|
@@ -11223,6 +11238,40 @@ var nextChatOrganizationIntervalSeconds = (interval, randomFraction) => {
|
|
|
11223
11238
|
const width = interval.maximumSeconds - interval.minimumSeconds + 1;
|
|
11224
11239
|
return interval.minimumSeconds + Math.floor(randomFraction * width);
|
|
11225
11240
|
};
|
|
11241
|
+
var initialChatOrganizationPacing = (currentSeconds) => ({
|
|
11242
|
+
currentSeconds,
|
|
11243
|
+
successStreak: 0,
|
|
11244
|
+
rateLimitCount: 0
|
|
11245
|
+
});
|
|
11246
|
+
var constrainChatOrganizationPacing = (pacing, options) => ({
|
|
11247
|
+
...pacing,
|
|
11248
|
+
currentSeconds: Math.min(
|
|
11249
|
+
options.maximumSeconds,
|
|
11250
|
+
Math.max(options.minimumSeconds, pacing.currentSeconds)
|
|
11251
|
+
),
|
|
11252
|
+
successStreak: Math.min(pacing.successStreak, options.speedUpAfter - 1)
|
|
11253
|
+
});
|
|
11254
|
+
var adaptiveChatOrganizationPacingAfterSuccess = (pacing, options) => {
|
|
11255
|
+
const successStreak = pacing.successStreak + 1;
|
|
11256
|
+
if (successStreak < options.speedUpAfter) return { ...pacing, successStreak };
|
|
11257
|
+
return {
|
|
11258
|
+
...pacing,
|
|
11259
|
+
currentSeconds: Math.min(
|
|
11260
|
+
pacing.currentSeconds,
|
|
11261
|
+
Math.max(options.minimumSeconds, Math.floor(pacing.currentSeconds * 0.8))
|
|
11262
|
+
),
|
|
11263
|
+
successStreak: 0
|
|
11264
|
+
};
|
|
11265
|
+
};
|
|
11266
|
+
var adaptiveChatOrganizationPacingAfterRateLimit = (pacing, options) => ({
|
|
11267
|
+
currentSeconds: Math.min(options.maximumSeconds, Math.ceil(pacing.currentSeconds * 1.5)),
|
|
11268
|
+
successStreak: 0,
|
|
11269
|
+
rateLimitCount: pacing.rateLimitCount + 1
|
|
11270
|
+
});
|
|
11271
|
+
var nextAdaptiveChatOrganizationIntervalSeconds = (pacing, randomFraction) => {
|
|
11272
|
+
const jitter = Math.max(1, Math.ceil(pacing.currentSeconds * 0.2));
|
|
11273
|
+
return pacing.currentSeconds + Math.floor(randomFraction * (jitter + 1));
|
|
11274
|
+
};
|
|
11226
11275
|
var chatOrganizationIntervalLabel = (interval) => {
|
|
11227
11276
|
if (interval.minimumSeconds === interval.maximumSeconds) return `${interval.minimumSeconds}s`;
|
|
11228
11277
|
return `${interval.minimumSeconds}-${interval.maximumSeconds}s`;
|
|
@@ -11299,11 +11348,98 @@ var persistChatOrganizationQueue = async (queuePath, queue) => {
|
|
|
11299
11348
|
}
|
|
11300
11349
|
}
|
|
11301
11350
|
};
|
|
11351
|
+
var updateChatOrganizationQueuePacing = (input) => ({
|
|
11352
|
+
...input.queue,
|
|
11353
|
+
pacing: input.pacing,
|
|
11354
|
+
updatedAt: input.timestamp
|
|
11355
|
+
});
|
|
11356
|
+
var updateChatOrganizationQueueVerification = (input) => ({
|
|
11357
|
+
...input.queue,
|
|
11358
|
+
verification: input.verification,
|
|
11359
|
+
updatedAt: input.timestamp
|
|
11360
|
+
});
|
|
11302
11361
|
var errorCodeOf = (error) => {
|
|
11303
11362
|
if (typeof error !== "object" || error === null || !("code" in error)) return void 0;
|
|
11304
11363
|
if (typeof error.code !== "string") return void 0;
|
|
11305
11364
|
return error.code;
|
|
11306
11365
|
};
|
|
11366
|
+
var chatOrganizationPausePath = (queuePath) => `${queuePath}.pause`;
|
|
11367
|
+
var chatOrganizationQueueIsPaused = async (queuePath) => existsSync(chatOrganizationPausePath(queuePath));
|
|
11368
|
+
var pauseChatOrganizationQueue = async (queuePath, timestamp) => {
|
|
11369
|
+
await mkdir7(dirname3(queuePath), { recursive: true });
|
|
11370
|
+
await writeFile5(
|
|
11371
|
+
chatOrganizationPausePath(queuePath),
|
|
11372
|
+
`${JSON.stringify({ pausedAt: timestamp })}
|
|
11373
|
+
`,
|
|
11374
|
+
"utf8"
|
|
11375
|
+
);
|
|
11376
|
+
};
|
|
11377
|
+
var clearChatOrganizationQueuePause = async (queuePath) => {
|
|
11378
|
+
try {
|
|
11379
|
+
await unlink(chatOrganizationPausePath(queuePath));
|
|
11380
|
+
} catch (error) {
|
|
11381
|
+
if (errorCodeOf(error) !== "ENOENT") throw error;
|
|
11382
|
+
}
|
|
11383
|
+
};
|
|
11384
|
+
var organizationQueueIsRunning = async (queuePath) => {
|
|
11385
|
+
let owner;
|
|
11386
|
+
try {
|
|
11387
|
+
owner = JSON.parse(await readFile10(`${queuePath}.lock`, "utf8"));
|
|
11388
|
+
} catch {
|
|
11389
|
+
return { running: false };
|
|
11390
|
+
}
|
|
11391
|
+
if (typeof owner !== "object" || owner === null || !("pid" in owner)) {
|
|
11392
|
+
return { running: false };
|
|
11393
|
+
}
|
|
11394
|
+
if (typeof owner.pid !== "number" || !Number.isInteger(owner.pid)) return { running: false };
|
|
11395
|
+
try {
|
|
11396
|
+
process.kill(owner.pid, 0);
|
|
11397
|
+
return { running: true, ownerPid: owner.pid };
|
|
11398
|
+
} catch (error) {
|
|
11399
|
+
if (errorCodeOf(error) === "ESRCH") return { running: false, ownerPid: owner.pid };
|
|
11400
|
+
return { running: true, ownerPid: owner.pid };
|
|
11401
|
+
}
|
|
11402
|
+
};
|
|
11403
|
+
var readChatOrganizationQueue = async (queuePath) => {
|
|
11404
|
+
const stored = JSON.parse(await readFile10(queuePath, "utf8"));
|
|
11405
|
+
return Schema8.decodeUnknownSync(ChatOrganizationQueueSchema)(stored);
|
|
11406
|
+
};
|
|
11407
|
+
var resolveChatOrganizationQueue = async (repoRoot, selector) => {
|
|
11408
|
+
const queueDirectory = join11(bridgeDir(repoRoot), "chat-organization-queues");
|
|
11409
|
+
let queuePath;
|
|
11410
|
+
if (selector?.trim()) {
|
|
11411
|
+
const trimmed = selector.trim();
|
|
11412
|
+
if (isAbsolute(trimmed) || trimmed.includes("/")) queuePath = resolve7(repoRoot, trimmed);
|
|
11413
|
+
else queuePath = join11(queueDirectory, trimmed.endsWith(".json") ? trimmed : `${trimmed}.json`);
|
|
11414
|
+
} else {
|
|
11415
|
+
let names;
|
|
11416
|
+
try {
|
|
11417
|
+
names = (await readdir5(queueDirectory)).filter((name) => /^[a-f0-9]{16}\.json$/u.test(name));
|
|
11418
|
+
} catch (error) {
|
|
11419
|
+
if (errorCodeOf(error) === "ENOENT") names = [];
|
|
11420
|
+
else throw error;
|
|
11421
|
+
}
|
|
11422
|
+
const queues = await Promise.all(
|
|
11423
|
+
names.map(async (name) => {
|
|
11424
|
+
const path2 = join11(queueDirectory, name);
|
|
11425
|
+
return { path: path2, queue: await readChatOrganizationQueue(path2) };
|
|
11426
|
+
})
|
|
11427
|
+
);
|
|
11428
|
+
queues.sort((left, right) => right.queue.updatedAt.localeCompare(left.queue.updatedAt));
|
|
11429
|
+
queuePath = queues[0]?.path;
|
|
11430
|
+
}
|
|
11431
|
+
if (queuePath === void 0 || !existsSync(queuePath)) {
|
|
11432
|
+
throw new Error("No persisted ChatGPT organization queue was found.");
|
|
11433
|
+
}
|
|
11434
|
+
const queue = await readChatOrganizationQueue(queuePath);
|
|
11435
|
+
const ownership = await organizationQueueIsRunning(queuePath);
|
|
11436
|
+
return {
|
|
11437
|
+
path: queuePath,
|
|
11438
|
+
queue,
|
|
11439
|
+
paused: await chatOrganizationQueueIsPaused(queuePath),
|
|
11440
|
+
...ownership
|
|
11441
|
+
};
|
|
11442
|
+
};
|
|
11307
11443
|
var removeStaleQueueLock = async (lockPath) => {
|
|
11308
11444
|
let owner;
|
|
11309
11445
|
try {
|
|
@@ -11434,6 +11570,47 @@ var summarizeChatOrganizationQueue = (queue) => {
|
|
|
11434
11570
|
}
|
|
11435
11571
|
return summary;
|
|
11436
11572
|
};
|
|
11573
|
+
var conversationIdentity = (value) => {
|
|
11574
|
+
const trimmed = value.trim();
|
|
11575
|
+
const conversationPath = /\/c\/(?<id>[^/?#]+)/u.exec(trimmed)?.groups?.id;
|
|
11576
|
+
if (conversationPath !== void 0) return conversationPath;
|
|
11577
|
+
return trimmed;
|
|
11578
|
+
};
|
|
11579
|
+
var reopenChatOrganizationQueueItems = (input) => {
|
|
11580
|
+
const targets = new Set(input.conversations.map(conversationIdentity));
|
|
11581
|
+
let changed = false;
|
|
11582
|
+
const items = input.queue.items.map((item) => {
|
|
11583
|
+
if (item.status !== "moved" && item.status !== "already-filed" || item.attempts >= input.maxAttempts || !targets.has(conversationIdentity(item.conversation))) {
|
|
11584
|
+
return item;
|
|
11585
|
+
}
|
|
11586
|
+
changed = true;
|
|
11587
|
+
return {
|
|
11588
|
+
status: "pending",
|
|
11589
|
+
conversation: item.conversation,
|
|
11590
|
+
project: item.project,
|
|
11591
|
+
attempts: item.attempts,
|
|
11592
|
+
lastReason: "Full-history audit found the Conversation still loose."
|
|
11593
|
+
};
|
|
11594
|
+
});
|
|
11595
|
+
if (!changed) return input.queue;
|
|
11596
|
+
return { ...input.queue, items, updatedAt: input.timestamp };
|
|
11597
|
+
};
|
|
11598
|
+
var chatOrganizationVerificationFrom = (input) => {
|
|
11599
|
+
const orphanIdentities = /* @__PURE__ */ new Set();
|
|
11600
|
+
for (const orphan of input.orphans) {
|
|
11601
|
+
orphanIdentities.add(conversationIdentity(orphan.id));
|
|
11602
|
+
orphanIdentities.add(orphan.title.trim());
|
|
11603
|
+
}
|
|
11604
|
+
const plannedStillLoose = input.queue.items.filter((item) => orphanIdentities.has(conversationIdentity(item.conversation))).map((item) => item.conversation);
|
|
11605
|
+
const summary = summarizeChatOrganizationQueue(input.queue);
|
|
11606
|
+
return {
|
|
11607
|
+
complete: summary.pending === 0 && summary.failed === 0 && plannedStillLoose.length === 0,
|
|
11608
|
+
inventoryComplete: true,
|
|
11609
|
+
remainingOrphans: input.orphans.length,
|
|
11610
|
+
plannedStillLoose,
|
|
11611
|
+
verifiedAt: input.timestamp
|
|
11612
|
+
};
|
|
11613
|
+
};
|
|
11437
11614
|
|
|
11438
11615
|
// src/features/terminal/providerLabel.ts
|
|
11439
11616
|
var providerDisplayName = (id2) => {
|
|
@@ -12000,7 +12177,7 @@ var applyInputSuggestion = (input, group, index = 0) => {
|
|
|
12000
12177
|
};
|
|
12001
12178
|
|
|
12002
12179
|
// src/features/terminal/tui/composer/fileAutocompleteComplete.ts
|
|
12003
|
-
import { readdir as
|
|
12180
|
+
import { readdir as readdir6 } from "fs/promises";
|
|
12004
12181
|
|
|
12005
12182
|
// src/features/terminal/tui/composer/fileAutocompleteTypes.ts
|
|
12006
12183
|
var DEFAULT_COMPLETION_LIMIT = 20;
|
|
@@ -12105,7 +12282,7 @@ var completionSearchDirectory = (input) => {
|
|
|
12105
12282
|
};
|
|
12106
12283
|
var readCompletionMatches = async (input) => {
|
|
12107
12284
|
try {
|
|
12108
|
-
const dirents = await
|
|
12285
|
+
const dirents = await readdir6(input.absoluteSearchDir, { withFileTypes: true });
|
|
12109
12286
|
return dirents.filter((dirent) => dirent.isDirectory() || dirent.isFile()).filter((dirent) => !IGNORED_COMPLETION_ENTRIES.has(dirent.name)).filter((dirent) => input.namePrefix.startsWith(".") || !dirent.name.startsWith(".")).filter((dirent) => dirent.name.startsWith(input.namePrefix)).map((dirent) => mapDirent({ dirent, dirPrefix: input.dirPrefix })).sort((left, right) => compareCompletionMatches(left, right)).slice(0, input.limit);
|
|
12110
12287
|
} catch {
|
|
12111
12288
|
return [];
|
|
@@ -12146,7 +12323,7 @@ var hasTrailingWhitespace = (input) => {
|
|
|
12146
12323
|
};
|
|
12147
12324
|
|
|
12148
12325
|
// src/features/terminal/tui/suggestions/repoPathSuggestions.ts
|
|
12149
|
-
import { readdir as
|
|
12326
|
+
import { readdir as readdir7 } from "fs/promises";
|
|
12150
12327
|
import { extname, sep as sep3 } from "path";
|
|
12151
12328
|
var IGNORED_COMPLETION_ENTRIES2 = /* @__PURE__ */ new Set([
|
|
12152
12329
|
".git",
|
|
@@ -12191,7 +12368,7 @@ var searchDirectory = (input) => {
|
|
|
12191
12368
|
};
|
|
12192
12369
|
var listMatchingEntries = async (input) => {
|
|
12193
12370
|
try {
|
|
12194
|
-
const entries = await
|
|
12371
|
+
const entries = await readdir7(input.absoluteSearchDir, { withFileTypes: true });
|
|
12195
12372
|
return entries.filter((entry) => isCompletableEntry({ name: entry.name, namePrefix: input.namePrefix })).filter((entry) => matchesKind({ entry, kind: input.kind, namePrefix: input.namePrefix })).map((entry) => pathEntrySuggestion(entry.name, input.dirPrefix, entry.isDirectory())).sort(comparePathSuggestions).slice(0, input.limit);
|
|
12196
12373
|
} catch {
|
|
12197
12374
|
return [];
|
|
@@ -15082,6 +15259,9 @@ var runChatMove = async (chat, options) => {
|
|
|
15082
15259
|
process.exit(outcomes.every((outcome) => outcome.moved || outcome.alreadyFiled) ? 0 : 1);
|
|
15083
15260
|
};
|
|
15084
15261
|
var DEFAULT_ORGANIZATION_INTERVAL_SECONDS = 60;
|
|
15262
|
+
var DEFAULT_ORGANIZATION_MIN_INTERVAL_SECONDS = 15;
|
|
15263
|
+
var DEFAULT_ORGANIZATION_MAX_INTERVAL_SECONDS = 180;
|
|
15264
|
+
var DEFAULT_ORGANIZATION_SPEED_UP_AFTER = 3;
|
|
15085
15265
|
var DEFAULT_ORGANIZATION_COOLDOWN_SECONDS = 600;
|
|
15086
15266
|
var DEFAULT_ORGANIZATION_MAX_ATTEMPTS = 4;
|
|
15087
15267
|
var MAX_CONSECUTIVE_ORGANIZATION_COOLDOWNS = 12;
|
|
@@ -15102,8 +15282,16 @@ var organizationIntervalOption = (value) => {
|
|
|
15102
15282
|
return fail(error instanceof Error ? error.message : String(error));
|
|
15103
15283
|
}
|
|
15104
15284
|
};
|
|
15105
|
-
var waitForOrganizationInterval = async (seconds) => {
|
|
15106
|
-
|
|
15285
|
+
var waitForOrganizationInterval = async (seconds, queuePath) => {
|
|
15286
|
+
let remainingMilliseconds = seconds * 1e3;
|
|
15287
|
+
while (remainingMilliseconds > 0) {
|
|
15288
|
+
if (await chatOrganizationQueueIsPaused(queuePath)) return "paused";
|
|
15289
|
+
const slice = Math.min(1e3, remainingMilliseconds);
|
|
15290
|
+
await new Promise((complete) => setTimeout(complete, slice));
|
|
15291
|
+
remainingMilliseconds -= slice;
|
|
15292
|
+
}
|
|
15293
|
+
if (await chatOrganizationQueueIsPaused(queuePath)) return "paused";
|
|
15294
|
+
return "elapsed";
|
|
15107
15295
|
};
|
|
15108
15296
|
var writeChatOrganizationProgress = (message, options) => {
|
|
15109
15297
|
if (options.json) {
|
|
@@ -15121,18 +15309,29 @@ var moveFailureReason = (outcome) => {
|
|
|
15121
15309
|
var writeChatOrganizationSummary = (input) => {
|
|
15122
15310
|
const summary = summarizeChatOrganizationQueue(input.queue);
|
|
15123
15311
|
if (input.options.json) {
|
|
15124
|
-
process.stdout.write(
|
|
15125
|
-
|
|
15312
|
+
process.stdout.write(
|
|
15313
|
+
`${JSON.stringify({
|
|
15314
|
+
queuePath: input.queuePath,
|
|
15315
|
+
state: input.paused ? "paused" : "finished",
|
|
15316
|
+
summary,
|
|
15317
|
+
pacing: input.queue.pacing,
|
|
15318
|
+
verification: input.queue.verification
|
|
15319
|
+
})}
|
|
15320
|
+
`
|
|
15321
|
+
);
|
|
15126
15322
|
return;
|
|
15127
15323
|
}
|
|
15128
15324
|
process.stdout.write(
|
|
15129
15325
|
`${[
|
|
15130
|
-
"Organization queue finished.",
|
|
15326
|
+
input.paused ? "Organization queue paused." : "Organization queue finished.",
|
|
15131
15327
|
`Moved: ${summary.moved}`,
|
|
15132
15328
|
`Already filed: ${summary.alreadyFiled}`,
|
|
15329
|
+
`Pending: ${summary.pending}`,
|
|
15133
15330
|
`Failed: ${summary.failed}`,
|
|
15331
|
+
input.queue.pacing === void 0 ? void 0 : `Adaptive pace: ${input.queue.pacing.currentSeconds}s base (${input.queue.pacing.rateLimitCount} rate limits)`,
|
|
15332
|
+
input.queue.verification === void 0 ? void 0 : `Full-history verification: ${input.queue.verification.complete ? "complete" : "incomplete"}; ${input.queue.verification.remainingOrphans} intentional/remaining orphans`,
|
|
15134
15333
|
`Queue state: ${input.queuePath}`
|
|
15135
|
-
].join("\n")}
|
|
15334
|
+
].filter((line) => line !== void 0).join("\n")}
|
|
15136
15335
|
`
|
|
15137
15336
|
);
|
|
15138
15337
|
};
|
|
@@ -15143,6 +15342,10 @@ var writeChatOrganizationDryRun = (input) => {
|
|
|
15143
15342
|
interval: input.interval,
|
|
15144
15343
|
cooldownSeconds: input.cooldownSeconds,
|
|
15145
15344
|
maxAttempts: input.maxAttempts,
|
|
15345
|
+
adaptive: input.adaptive,
|
|
15346
|
+
minimumIntervalSeconds: input.minimumIntervalSeconds,
|
|
15347
|
+
maximumIntervalSeconds: input.maximumIntervalSeconds,
|
|
15348
|
+
speedUpAfter: input.speedUpAfter,
|
|
15146
15349
|
tasks: input.tasks
|
|
15147
15350
|
};
|
|
15148
15351
|
if (input.options.json) {
|
|
@@ -15154,6 +15357,7 @@ var writeChatOrganizationDryRun = (input) => {
|
|
|
15154
15357
|
`${[
|
|
15155
15358
|
`Organization queue dry run: ${input.tasks.length} Conversations`,
|
|
15156
15359
|
`Interval: ${chatOrganizationIntervalLabel(input.interval)}`,
|
|
15360
|
+
`Adaptive pacing: ${input.adaptive ? `yes (${input.minimumIntervalSeconds}-${input.maximumIntervalSeconds}s; speed up after ${input.speedUpAfter} successes)` : "no"}`,
|
|
15157
15361
|
`Rate-limit cooldown: ${input.cooldownSeconds}s`,
|
|
15158
15362
|
`Attempts per Conversation: ${input.maxAttempts}`,
|
|
15159
15363
|
`Resume state: ${input.queuePath}`,
|
|
@@ -15208,6 +15412,132 @@ var recordChatOrganizationAttempt = async (input) => {
|
|
|
15208
15412
|
await persistChatOrganizationQueue(input.queuePath, queue);
|
|
15209
15413
|
return queue;
|
|
15210
15414
|
};
|
|
15415
|
+
var persistChatOrganizationPacing = async (input) => {
|
|
15416
|
+
const queue = updateChatOrganizationQueuePacing({
|
|
15417
|
+
queue: input.queue,
|
|
15418
|
+
pacing: input.pacing,
|
|
15419
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
15420
|
+
});
|
|
15421
|
+
await persistChatOrganizationQueue(input.queuePath, queue);
|
|
15422
|
+
return queue;
|
|
15423
|
+
};
|
|
15424
|
+
var verifyCompletedChatOrganizationQueue = async (input) => {
|
|
15425
|
+
writeChatOrganizationProgress(
|
|
15426
|
+
"Verifying the completed plan against an exhaustive full-history orphan scan.",
|
|
15427
|
+
input.options
|
|
15428
|
+
);
|
|
15429
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
15430
|
+
let verification;
|
|
15431
|
+
try {
|
|
15432
|
+
const orphans = await input.workspace.engine.getOrchestrator().listConversations({ orphans: true });
|
|
15433
|
+
verification = chatOrganizationVerificationFrom({
|
|
15434
|
+
queue: input.queue,
|
|
15435
|
+
orphans,
|
|
15436
|
+
timestamp
|
|
15437
|
+
});
|
|
15438
|
+
} catch (error) {
|
|
15439
|
+
verification = {
|
|
15440
|
+
complete: false,
|
|
15441
|
+
inventoryComplete: false,
|
|
15442
|
+
remainingOrphans: 0,
|
|
15443
|
+
plannedStillLoose: [],
|
|
15444
|
+
verifiedAt: timestamp,
|
|
15445
|
+
error: error instanceof Error ? error.message : String(error)
|
|
15446
|
+
};
|
|
15447
|
+
}
|
|
15448
|
+
let queue = updateChatOrganizationQueueVerification({
|
|
15449
|
+
queue: input.queue,
|
|
15450
|
+
verification,
|
|
15451
|
+
timestamp
|
|
15452
|
+
});
|
|
15453
|
+
if (verification.plannedStillLoose.length > 0) {
|
|
15454
|
+
queue = reopenChatOrganizationQueueItems({
|
|
15455
|
+
queue,
|
|
15456
|
+
conversations: verification.plannedStillLoose,
|
|
15457
|
+
maxAttempts: input.maxAttempts,
|
|
15458
|
+
timestamp
|
|
15459
|
+
});
|
|
15460
|
+
}
|
|
15461
|
+
await persistChatOrganizationQueue(input.queuePath, queue);
|
|
15462
|
+
if (verification.inventoryComplete) {
|
|
15463
|
+
writeChatOrganizationProgress(
|
|
15464
|
+
`Full-history scan reached the stable end: ${verification.remainingOrphans} loose Conversations remain; ${verification.plannedStillLoose.length} planned Conversations are still loose.`,
|
|
15465
|
+
input.options
|
|
15466
|
+
);
|
|
15467
|
+
} else {
|
|
15468
|
+
writeChatOrganizationProgress(
|
|
15469
|
+
`Full-history verification could not prove completion: ${verification.error ?? "unknown scan failure"}`,
|
|
15470
|
+
input.options
|
|
15471
|
+
);
|
|
15472
|
+
}
|
|
15473
|
+
return queue;
|
|
15474
|
+
};
|
|
15475
|
+
var organizationQueueState = (input) => {
|
|
15476
|
+
if (input.running) return input.paused ? "pausing" : "running";
|
|
15477
|
+
if (input.paused) return "paused";
|
|
15478
|
+
if (input.summary.pending === 0) return input.summary.failed > 0 ? "failed" : "completed";
|
|
15479
|
+
return "idle";
|
|
15480
|
+
};
|
|
15481
|
+
var runChatOrganizeStatus = async (options) => {
|
|
15482
|
+
const selected = await resolveChatOrganizationQueue(repositoryRoot(options.repo), options.queue);
|
|
15483
|
+
const summary = summarizeChatOrganizationQueue(selected.queue);
|
|
15484
|
+
const state = organizationQueueState({
|
|
15485
|
+
paused: selected.paused,
|
|
15486
|
+
running: selected.running,
|
|
15487
|
+
summary
|
|
15488
|
+
});
|
|
15489
|
+
const status = {
|
|
15490
|
+
state,
|
|
15491
|
+
queuePath: selected.path,
|
|
15492
|
+
ownerPid: selected.ownerPid,
|
|
15493
|
+
summary,
|
|
15494
|
+
pacing: selected.queue.pacing,
|
|
15495
|
+
verification: selected.queue.verification
|
|
15496
|
+
};
|
|
15497
|
+
if (options.json) process.stdout.write(`${JSON.stringify(status)}
|
|
15498
|
+
`);
|
|
15499
|
+
else {
|
|
15500
|
+
process.stdout.write(
|
|
15501
|
+
`${[
|
|
15502
|
+
`Organization queue: ${state}`,
|
|
15503
|
+
`Moved: ${summary.moved}`,
|
|
15504
|
+
`Already filed: ${summary.alreadyFiled}`,
|
|
15505
|
+
`Pending: ${summary.pending}`,
|
|
15506
|
+
`Failed: ${summary.failed}`,
|
|
15507
|
+
selected.queue.pacing === void 0 ? "Adaptive pace: not initialized" : `Adaptive pace: ${selected.queue.pacing.currentSeconds}s base (${selected.queue.pacing.successStreak} success streak; ${selected.queue.pacing.rateLimitCount} rate limits)`,
|
|
15508
|
+
selected.queue.verification === void 0 ? "Full-history verification: not run" : `Full-history verification: ${selected.queue.verification.complete ? "complete" : "incomplete"}`,
|
|
15509
|
+
`Queue state: ${selected.path}`
|
|
15510
|
+
].join("\n")}
|
|
15511
|
+
`
|
|
15512
|
+
);
|
|
15513
|
+
}
|
|
15514
|
+
};
|
|
15515
|
+
var runChatOrganizePause = async (options) => {
|
|
15516
|
+
const selected = await resolveChatOrganizationQueue(repositoryRoot(options.repo), options.queue);
|
|
15517
|
+
await pauseChatOrganizationQueue(selected.path, (/* @__PURE__ */ new Date()).toISOString());
|
|
15518
|
+
const message = selected.running ? "Pause requested; the active UI operation will finish before the queue releases its lock." : "Organization queue paused.";
|
|
15519
|
+
if (options.json) {
|
|
15520
|
+
process.stdout.write(
|
|
15521
|
+
`${JSON.stringify({ state: selected.running ? "pausing" : "paused", queuePath: selected.path })}
|
|
15522
|
+
`
|
|
15523
|
+
);
|
|
15524
|
+
} else process.stdout.write(`${message}
|
|
15525
|
+
Queue state: ${selected.path}
|
|
15526
|
+
`);
|
|
15527
|
+
};
|
|
15528
|
+
var runChatOrganizeResume = async (options) => {
|
|
15529
|
+
assertChatgptWorkspace(options);
|
|
15530
|
+
const selected = await resolveChatOrganizationQueue(repositoryRoot(options.repo), options.queue);
|
|
15531
|
+
if (selected.running) return fail(`Organization queue is already running: ${selected.path}`);
|
|
15532
|
+
await clearChatOrganizationQueuePause(selected.path);
|
|
15533
|
+
const plan = JSON.stringify(
|
|
15534
|
+
selected.queue.items.map((item) => ({
|
|
15535
|
+
conversation: item.conversation,
|
|
15536
|
+
project: item.project
|
|
15537
|
+
}))
|
|
15538
|
+
);
|
|
15539
|
+
return runChatOrganize({ ...options, plan, restart: false, dryRun: false });
|
|
15540
|
+
};
|
|
15211
15541
|
var runChatOrganize = async (options) => {
|
|
15212
15542
|
assertChatgptWorkspace(options);
|
|
15213
15543
|
const plan = options.plan;
|
|
@@ -15215,6 +15545,25 @@ var runChatOrganize = async (options) => {
|
|
|
15215
15545
|
return fail("Usage: bridge chat organize --plan <fileOrJson>");
|
|
15216
15546
|
}
|
|
15217
15547
|
const interval = organizationIntervalOption(options.interval);
|
|
15548
|
+
const adaptive = options.adaptive !== false;
|
|
15549
|
+
const minimumIntervalSeconds = positiveIntegerOption(
|
|
15550
|
+
options.minInterval,
|
|
15551
|
+
"--min-interval",
|
|
15552
|
+
DEFAULT_ORGANIZATION_MIN_INTERVAL_SECONDS
|
|
15553
|
+
);
|
|
15554
|
+
const maximumIntervalSeconds = positiveIntegerOption(
|
|
15555
|
+
options.maxInterval,
|
|
15556
|
+
"--max-interval",
|
|
15557
|
+
DEFAULT_ORGANIZATION_MAX_INTERVAL_SECONDS
|
|
15558
|
+
);
|
|
15559
|
+
if (maximumIntervalSeconds < minimumIntervalSeconds) {
|
|
15560
|
+
return fail("--max-interval must be greater than or equal to --min-interval.");
|
|
15561
|
+
}
|
|
15562
|
+
const speedUpAfter = positiveIntegerOption(
|
|
15563
|
+
options.speedUpAfter,
|
|
15564
|
+
"--speed-up-after",
|
|
15565
|
+
DEFAULT_ORGANIZATION_SPEED_UP_AFTER
|
|
15566
|
+
);
|
|
15218
15567
|
const cooldownSeconds = positiveIntegerOption(
|
|
15219
15568
|
options.cooldown,
|
|
15220
15569
|
"--cooldown",
|
|
@@ -15240,6 +15589,10 @@ var runChatOrganize = async (options) => {
|
|
|
15240
15589
|
interval,
|
|
15241
15590
|
cooldownSeconds,
|
|
15242
15591
|
maxAttempts,
|
|
15592
|
+
adaptive,
|
|
15593
|
+
minimumIntervalSeconds,
|
|
15594
|
+
maximumIntervalSeconds,
|
|
15595
|
+
speedUpAfter,
|
|
15243
15596
|
options
|
|
15244
15597
|
});
|
|
15245
15598
|
process.exit(0);
|
|
@@ -15259,6 +15612,26 @@ var runChatOrganize = async (options) => {
|
|
|
15259
15612
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
15260
15613
|
});
|
|
15261
15614
|
queue = opened.queue;
|
|
15615
|
+
if (adaptive) {
|
|
15616
|
+
const pacing = queue.pacing === void 0 ? initialChatOrganizationPacing(
|
|
15617
|
+
Math.min(
|
|
15618
|
+
maximumIntervalSeconds,
|
|
15619
|
+
Math.max(
|
|
15620
|
+
minimumIntervalSeconds,
|
|
15621
|
+
nextChatOrganizationIntervalSeconds(interval, Math.random())
|
|
15622
|
+
)
|
|
15623
|
+
)
|
|
15624
|
+
) : constrainChatOrganizationPacing(queue.pacing, {
|
|
15625
|
+
minimumSeconds: minimumIntervalSeconds,
|
|
15626
|
+
maximumSeconds: maximumIntervalSeconds,
|
|
15627
|
+
speedUpAfter
|
|
15628
|
+
});
|
|
15629
|
+
queue = await persistChatOrganizationPacing({
|
|
15630
|
+
queue,
|
|
15631
|
+
queuePath,
|
|
15632
|
+
pacing
|
|
15633
|
+
});
|
|
15634
|
+
}
|
|
15262
15635
|
} catch (error) {
|
|
15263
15636
|
await releaseQueueLock();
|
|
15264
15637
|
return fail(
|
|
@@ -15270,10 +15643,13 @@ var runChatOrganize = async (options) => {
|
|
|
15270
15643
|
`Organization queue: ${initialSummary.pending} pending of ${initialSummary.total}; state ${queuePath}`,
|
|
15271
15644
|
options
|
|
15272
15645
|
);
|
|
15273
|
-
|
|
15646
|
+
const needsVerification = options.verify !== false && queue.verification?.complete !== true;
|
|
15647
|
+
if (initialSummary.pending === 0 && !needsVerification) {
|
|
15274
15648
|
writeChatOrganizationSummary({ queuePath, queue, options });
|
|
15275
15649
|
await releaseQueueLock();
|
|
15276
|
-
process.exit(
|
|
15650
|
+
process.exit(
|
|
15651
|
+
initialSummary.failed === 0 && (options.verify === false || queue.verification?.complete === true) ? 0 : 1
|
|
15652
|
+
);
|
|
15277
15653
|
}
|
|
15278
15654
|
let workspace;
|
|
15279
15655
|
try {
|
|
@@ -15283,106 +15659,171 @@ var runChatOrganize = async (options) => {
|
|
|
15283
15659
|
throw error;
|
|
15284
15660
|
}
|
|
15285
15661
|
let workspaceWasShutdown = false;
|
|
15662
|
+
let paused = false;
|
|
15286
15663
|
try {
|
|
15287
|
-
let index = nextChatOrganizationQueueIndex(queue);
|
|
15288
15664
|
let consecutiveRateLimitCooldowns = 0;
|
|
15289
|
-
|
|
15290
|
-
|
|
15291
|
-
|
|
15292
|
-
|
|
15293
|
-
|
|
15294
|
-
|
|
15295
|
-
if (await acknowledgeChatGptHistoryRateLimit(workspace.page)) {
|
|
15296
|
-
consecutiveRateLimitCooldowns += 1;
|
|
15297
|
-
if (consecutiveRateLimitCooldowns >= MAX_CONSECUTIVE_ORGANIZATION_COOLDOWNS) {
|
|
15665
|
+
let halted = false;
|
|
15666
|
+
while (!paused && !halted) {
|
|
15667
|
+
let index = nextChatOrganizationQueueIndex(queue);
|
|
15668
|
+
while (index !== void 0) {
|
|
15669
|
+
if (await chatOrganizationQueueIsPaused(queuePath)) {
|
|
15670
|
+
paused = true;
|
|
15298
15671
|
writeChatOrganizationProgress(
|
|
15299
|
-
|
|
15672
|
+
"Organization queue pause acknowledged; no new UI operation will start.",
|
|
15300
15673
|
options
|
|
15301
15674
|
);
|
|
15302
15675
|
break;
|
|
15303
15676
|
}
|
|
15677
|
+
const item = queue.items[index];
|
|
15678
|
+
if (item === void 0 || item.status !== "pending") {
|
|
15679
|
+
index = nextChatOrganizationQueueIndex(queue);
|
|
15680
|
+
continue;
|
|
15681
|
+
}
|
|
15682
|
+
if (await acknowledgeChatGptHistoryRateLimit(workspace.page)) {
|
|
15683
|
+
consecutiveRateLimitCooldowns += 1;
|
|
15684
|
+
if (adaptive && queue.pacing !== void 0) {
|
|
15685
|
+
queue = await persistChatOrganizationPacing({
|
|
15686
|
+
queue,
|
|
15687
|
+
queuePath,
|
|
15688
|
+
pacing: adaptiveChatOrganizationPacingAfterRateLimit(queue.pacing, {
|
|
15689
|
+
maximumSeconds: maximumIntervalSeconds
|
|
15690
|
+
})
|
|
15691
|
+
});
|
|
15692
|
+
}
|
|
15693
|
+
if (consecutiveRateLimitCooldowns >= MAX_CONSECUTIVE_ORGANIZATION_COOLDOWNS) {
|
|
15694
|
+
writeChatOrganizationProgress(
|
|
15695
|
+
`ChatGPT remained rate-limited after ${consecutiveRateLimitCooldowns} cooldowns; leaving the queue pending for a later resume.`,
|
|
15696
|
+
options
|
|
15697
|
+
);
|
|
15698
|
+
halted = true;
|
|
15699
|
+
break;
|
|
15700
|
+
}
|
|
15701
|
+
writeChatOrganizationProgress(
|
|
15702
|
+
`ChatGPT rate limit detected; cooling down for ${cooldownSeconds}s before continuing${queue.pacing === void 0 ? "." : ` at a slower ${queue.pacing.currentSeconds}s adaptive pace.`}`,
|
|
15703
|
+
options
|
|
15704
|
+
);
|
|
15705
|
+
if (await waitForOrganizationInterval(cooldownSeconds, queuePath) === "paused") {
|
|
15706
|
+
paused = true;
|
|
15707
|
+
break;
|
|
15708
|
+
}
|
|
15709
|
+
continue;
|
|
15710
|
+
}
|
|
15711
|
+
consecutiveRateLimitCooldowns = 0;
|
|
15304
15712
|
writeChatOrganizationProgress(
|
|
15305
|
-
`
|
|
15306
|
-
options
|
|
15307
|
-
);
|
|
15308
|
-
await waitForOrganizationInterval(cooldownSeconds);
|
|
15309
|
-
continue;
|
|
15310
|
-
}
|
|
15311
|
-
consecutiveRateLimitCooldowns = 0;
|
|
15312
|
-
writeChatOrganizationProgress(
|
|
15313
|
-
`Moving "${item.conversation}" -> ${item.project} (attempt ${item.attempts + 1}/${maxAttempts})`,
|
|
15314
|
-
options
|
|
15315
|
-
);
|
|
15316
|
-
let moveOutcome;
|
|
15317
|
-
let thrownReason;
|
|
15318
|
-
try {
|
|
15319
|
-
moveOutcome = await moveChatToProject(workspace.page, {
|
|
15320
|
-
chat: item.conversation,
|
|
15321
|
-
project: item.project
|
|
15322
|
-
});
|
|
15323
|
-
} catch (error) {
|
|
15324
|
-
thrownReason = error instanceof Error ? error.message : String(error);
|
|
15325
|
-
}
|
|
15326
|
-
const sessionClosed = chatOrganizationSessionWasClosed(thrownReason);
|
|
15327
|
-
const rateLimited = await acknowledgeChatGptHistoryRateLimit(workspace.page);
|
|
15328
|
-
queue = await recordChatOrganizationAttempt({
|
|
15329
|
-
queue,
|
|
15330
|
-
queuePath,
|
|
15331
|
-
index,
|
|
15332
|
-
maxAttempts,
|
|
15333
|
-
sessionClosed,
|
|
15334
|
-
rateLimited,
|
|
15335
|
-
moveOutcome,
|
|
15336
|
-
thrownReason
|
|
15337
|
-
});
|
|
15338
|
-
if (sessionClosed) {
|
|
15339
|
-
writeChatOrganizationProgress(
|
|
15340
|
-
"ChatGPT browser session closed; reopening it without consuming a retry attempt.",
|
|
15713
|
+
`Moving "${item.conversation}" -> ${item.project} (attempt ${item.attempts + 1}/${maxAttempts})`,
|
|
15341
15714
|
options
|
|
15342
15715
|
);
|
|
15343
|
-
|
|
15344
|
-
|
|
15716
|
+
let moveOutcome;
|
|
15717
|
+
let thrownReason;
|
|
15345
15718
|
try {
|
|
15346
|
-
|
|
15347
|
-
|
|
15719
|
+
moveOutcome = await moveChatToProject(workspace.page, {
|
|
15720
|
+
chat: item.conversation,
|
|
15721
|
+
project: item.project
|
|
15722
|
+
});
|
|
15348
15723
|
} catch (error) {
|
|
15724
|
+
thrownReason = error instanceof Error ? error.message : String(error);
|
|
15725
|
+
}
|
|
15726
|
+
const sessionClosed = chatOrganizationSessionWasClosed(thrownReason);
|
|
15727
|
+
const rateLimited = await acknowledgeChatGptHistoryRateLimit(workspace.page);
|
|
15728
|
+
queue = await recordChatOrganizationAttempt({
|
|
15729
|
+
queue,
|
|
15730
|
+
queuePath,
|
|
15731
|
+
index,
|
|
15732
|
+
maxAttempts,
|
|
15733
|
+
sessionClosed,
|
|
15734
|
+
rateLimited,
|
|
15735
|
+
moveOutcome,
|
|
15736
|
+
thrownReason
|
|
15737
|
+
});
|
|
15738
|
+
if (adaptive && queue.pacing !== void 0) {
|
|
15739
|
+
let pacing = queue.pacing;
|
|
15740
|
+
if (rateLimited) {
|
|
15741
|
+
pacing = adaptiveChatOrganizationPacingAfterRateLimit(pacing, {
|
|
15742
|
+
maximumSeconds: maximumIntervalSeconds
|
|
15743
|
+
});
|
|
15744
|
+
} else if (moveOutcome?.moved || moveOutcome?.alreadyFiled) {
|
|
15745
|
+
pacing = adaptiveChatOrganizationPacingAfterSuccess(pacing, {
|
|
15746
|
+
minimumSeconds: minimumIntervalSeconds,
|
|
15747
|
+
speedUpAfter
|
|
15748
|
+
});
|
|
15749
|
+
} else if (pacing.successStreak > 0) {
|
|
15750
|
+
pacing = { ...pacing, successStreak: 0 };
|
|
15751
|
+
}
|
|
15752
|
+
queue = await persistChatOrganizationPacing({ queue, queuePath, pacing });
|
|
15753
|
+
}
|
|
15754
|
+
if (sessionClosed) {
|
|
15349
15755
|
writeChatOrganizationProgress(
|
|
15350
|
-
|
|
15756
|
+
"ChatGPT browser session closed; reopening it without consuming a retry attempt.",
|
|
15351
15757
|
options
|
|
15352
15758
|
);
|
|
15353
|
-
|
|
15759
|
+
await workspace.engine.shutdown({ closeBrowser: false });
|
|
15760
|
+
workspaceWasShutdown = true;
|
|
15761
|
+
try {
|
|
15762
|
+
workspace = await startWorkspaceSession(options);
|
|
15763
|
+
workspaceWasShutdown = false;
|
|
15764
|
+
} catch (error) {
|
|
15765
|
+
writeChatOrganizationProgress(
|
|
15766
|
+
`Could not reopen the ChatGPT browser session; leaving the queue pending: ${error instanceof Error ? error.message : String(error)}`,
|
|
15767
|
+
options
|
|
15768
|
+
);
|
|
15769
|
+
halted = true;
|
|
15770
|
+
break;
|
|
15771
|
+
}
|
|
15772
|
+
index = nextChatOrganizationQueueIndex(queue);
|
|
15773
|
+
continue;
|
|
15774
|
+
}
|
|
15775
|
+
const recorded = queue.items[index];
|
|
15776
|
+
if (recorded?.status === "moved") {
|
|
15777
|
+
writeChatOrganizationProgress(`Moved "${recorded.conversation}".`, options);
|
|
15778
|
+
} else if (recorded?.status === "already-filed") {
|
|
15779
|
+
writeChatOrganizationProgress(`Already filed "${recorded.conversation}".`, options);
|
|
15780
|
+
} else if (recorded?.status === "failed") {
|
|
15781
|
+
writeChatOrganizationProgress(
|
|
15782
|
+
`Failed "${recorded.conversation}" after ${recorded.attempts} attempts: ${recorded.reason}`,
|
|
15783
|
+
options
|
|
15784
|
+
);
|
|
15785
|
+
} else if (recorded?.status === "pending") {
|
|
15786
|
+
let reason = "unknown failure";
|
|
15787
|
+
if (recorded.lastReason !== void 0) reason = recorded.lastReason;
|
|
15788
|
+
writeChatOrganizationProgress(
|
|
15789
|
+
`Will retry "${recorded.conversation}": ${reason}`,
|
|
15790
|
+
options
|
|
15791
|
+
);
|
|
15792
|
+
}
|
|
15793
|
+
let waitSeconds = adaptive && queue.pacing !== void 0 ? nextAdaptiveChatOrganizationIntervalSeconds(queue.pacing, Math.random()) : nextChatOrganizationIntervalSeconds(interval, Math.random());
|
|
15794
|
+
if (rateLimited) {
|
|
15795
|
+
consecutiveRateLimitCooldowns += 1;
|
|
15796
|
+
waitSeconds = cooldownSeconds;
|
|
15354
15797
|
}
|
|
15355
15798
|
index = nextChatOrganizationQueueIndex(queue);
|
|
15356
|
-
|
|
15357
|
-
|
|
15358
|
-
|
|
15359
|
-
|
|
15360
|
-
|
|
15361
|
-
|
|
15362
|
-
|
|
15363
|
-
|
|
15364
|
-
|
|
15365
|
-
|
|
15366
|
-
options
|
|
15367
|
-
);
|
|
15368
|
-
} else if (recorded?.status === "pending") {
|
|
15369
|
-
let reason = "unknown failure";
|
|
15370
|
-
if (recorded.lastReason !== void 0) reason = recorded.lastReason;
|
|
15371
|
-
writeChatOrganizationProgress(`Will retry "${recorded.conversation}": ${reason}`, options);
|
|
15372
|
-
}
|
|
15373
|
-
let waitSeconds = nextChatOrganizationIntervalSeconds(interval, Math.random());
|
|
15374
|
-
if (rateLimited) {
|
|
15375
|
-
consecutiveRateLimitCooldowns += 1;
|
|
15376
|
-
waitSeconds = cooldownSeconds;
|
|
15799
|
+
if (index !== void 0) {
|
|
15800
|
+
writeChatOrganizationProgress(
|
|
15801
|
+
`Waiting ${waitSeconds}s before the next UI operation${adaptive ? " (adaptive)." : "."}`,
|
|
15802
|
+
options
|
|
15803
|
+
);
|
|
15804
|
+
if (await waitForOrganizationInterval(waitSeconds, queuePath) === "paused") {
|
|
15805
|
+
paused = true;
|
|
15806
|
+
break;
|
|
15807
|
+
}
|
|
15808
|
+
}
|
|
15377
15809
|
}
|
|
15378
|
-
|
|
15379
|
-
if (
|
|
15380
|
-
|
|
15381
|
-
|
|
15382
|
-
|
|
15383
|
-
|
|
15384
|
-
|
|
15810
|
+
if (paused || halted) break;
|
|
15811
|
+
if (options.verify !== false && summarizeChatOrganizationQueue(queue).pending === 0) {
|
|
15812
|
+
queue = await verifyCompletedChatOrganizationQueue({
|
|
15813
|
+
queue,
|
|
15814
|
+
queuePath,
|
|
15815
|
+
workspace,
|
|
15816
|
+
options,
|
|
15817
|
+
maxAttempts
|
|
15818
|
+
});
|
|
15385
15819
|
}
|
|
15820
|
+
const reopened = nextChatOrganizationQueueIndex(queue);
|
|
15821
|
+
if (reopened === void 0) break;
|
|
15822
|
+
writeChatOrganizationProgress(
|
|
15823
|
+
"The full-history audit found planned Conversations still loose; retrying them automatically.",
|
|
15824
|
+
options
|
|
15825
|
+
);
|
|
15826
|
+
consecutiveRateLimitCooldowns = 0;
|
|
15386
15827
|
}
|
|
15387
15828
|
} finally {
|
|
15388
15829
|
try {
|
|
@@ -15392,9 +15833,12 @@ var runChatOrganize = async (options) => {
|
|
|
15392
15833
|
}
|
|
15393
15834
|
}
|
|
15394
15835
|
const summary = summarizeChatOrganizationQueue(queue);
|
|
15395
|
-
writeChatOrganizationSummary({ queuePath, queue, options });
|
|
15836
|
+
writeChatOrganizationSummary({ queuePath, queue, options, paused });
|
|
15837
|
+
if (paused) process.exit(0);
|
|
15396
15838
|
let exitCode = 0;
|
|
15397
|
-
if (summary.failed > 0 || summary.pending > 0
|
|
15839
|
+
if (summary.failed > 0 || summary.pending > 0 || options.verify !== false && queue.verification?.complete !== true) {
|
|
15840
|
+
exitCode = 1;
|
|
15841
|
+
}
|
|
15398
15842
|
process.exit(exitCode);
|
|
15399
15843
|
};
|
|
15400
15844
|
var writeArchiveOutcomes = (outcomes, options) => {
|
|
@@ -15855,7 +16299,7 @@ var subcommandOpts = (command) => {
|
|
|
15855
16299
|
// src/features/terminal/registerCli.ts
|
|
15856
16300
|
var PROVIDER_OPTION = `Browser provider: ${PROVIDER_IDS.join(", ")} (default: ${DEFAULT_PROVIDER})`;
|
|
15857
16301
|
var registerCliCommands = (program) => {
|
|
15858
|
-
program.name("bridge").description("Terminal CLI that bridges ChatGPT or Gemini with local tools via MCP").version("0.
|
|
16302
|
+
program.name("bridge").description("Terminal CLI that bridges ChatGPT or Gemini with local tools via MCP").version("0.6.0").option("-r, --repo <path>", "Path to the target repository (default: cwd)").option("-p, --port <number>", "MCP server port (default: 8765)").option("--provider <name>", PROVIDER_OPTION).option("--no-browser", "Skip Chrome browser connection").action(async (_options, command) => {
|
|
15859
16303
|
if (process.stdin.isTTY !== true || process.stdout.isTTY !== true) {
|
|
15860
16304
|
command.outputHelp({ error: true });
|
|
15861
16305
|
process.exitCode = 1;
|
|
@@ -15957,6 +16401,15 @@ var withWorkspaceFlags = (command) => {
|
|
|
15957
16401
|
"Chrome user-data-dir to drive (parallel accounts; default shared bridge profile)"
|
|
15958
16402
|
).option("--json", "Emit JSON instead of human-readable lines");
|
|
15959
16403
|
};
|
|
16404
|
+
var withOrganizationPacingFlags = (command) => {
|
|
16405
|
+
return command.option(
|
|
16406
|
+
"--interval <secondsOrRange>",
|
|
16407
|
+
"Initial seconds between UI operations, fixed or random range such as 60-90 (default: 60)"
|
|
16408
|
+
).option("--no-adaptive", "Keep the initial interval instead of adapting to success/limits").option("--min-interval <seconds>", "Fastest adaptive base interval (default: 15)").option("--max-interval <seconds>", "Slowest adaptive base interval (default: 180)").option(
|
|
16409
|
+
"--speed-up-after <count>",
|
|
16410
|
+
"Successful moves before reducing the adaptive interval (default: 3)"
|
|
16411
|
+
).option("--cooldown <seconds>", "Seconds to wait after rate limiting (default: 600)").option("--max-attempts <count>", "Attempts per Conversation before failing (default: 4)").option("--no-verify", "Skip the exhaustive orphan scan when the queue finishes");
|
|
16412
|
+
};
|
|
15960
16413
|
var registerWorkspaceCommands = (program) => {
|
|
15961
16414
|
const project = program.command("project").description("Manage ChatGPT Projects (ChatGPT only)");
|
|
15962
16415
|
withWorkspaceFlags(project.command("list")).description("List ChatGPT Projects").action(
|
|
@@ -15984,15 +16437,21 @@ var registerWorkspaceCommands = (program) => {
|
|
|
15984
16437
|
withWorkspaceFlags(chat.command("archive [idOrTitle...]")).description("Archive one or more conversations (reversible \u2014 hides from the sidebar)").option("--id <id...>", "Archive several conversations by id in one session").action(
|
|
15985
16438
|
(chatParts, _options, command) => runChatArchive(chatParts.join(" "), command.optsWithGlobals())
|
|
15986
16439
|
);
|
|
15987
|
-
withWorkspaceFlags(chat.command("organize")).description("Run a resumable, rate-safe Conversation organization queue").
|
|
16440
|
+
const organize = withOrganizationPacingFlags(withWorkspaceFlags(chat.command("organize"))).description("Run a resumable, rate-safe Conversation organization queue").option(
|
|
15988
16441
|
"--plan <fileOrJson>",
|
|
15989
16442
|
"JSON array of {conversation, project} tasks (inline, @file, or a path)"
|
|
15990
|
-
).option(
|
|
15991
|
-
"--interval <secondsOrRange>",
|
|
15992
|
-
"Seconds between UI operations, fixed or random range such as 60-90 (default: 60)"
|
|
15993
|
-
).option("--cooldown <seconds>", "Seconds to wait after rate limiting (default: 600)").option("--max-attempts <count>", "Attempts per Conversation before failing (default: 4)").option("--restart", "Restart this plan instead of resuming its persisted queue").option("--dry-run", "Validate and show the queue without opening Chrome or writing state").action(
|
|
16443
|
+
).option("--restart", "Restart this plan instead of resuming its persisted queue").option("--dry-run", "Validate and show the queue without opening Chrome or writing state").action(
|
|
15994
16444
|
(_options, command) => runChatOrganize(command.optsWithGlobals())
|
|
15995
16445
|
);
|
|
16446
|
+
withWorkspaceFlags(organize.command("status")).description("Show the latest organization queue state and adaptive pace").option("--queue <pathOrFingerprint>", "Select a queue instead of the latest one").action(
|
|
16447
|
+
(_options, command) => runChatOrganizeStatus(command.optsWithGlobals())
|
|
16448
|
+
);
|
|
16449
|
+
withWorkspaceFlags(organize.command("pause")).description("Pause the latest queue after its active UI operation").option("--queue <pathOrFingerprint>", "Select a queue instead of the latest one").action(
|
|
16450
|
+
(_options, command) => runChatOrganizePause(command.optsWithGlobals())
|
|
16451
|
+
);
|
|
16452
|
+
withOrganizationPacingFlags(withWorkspaceFlags(organize.command("resume"))).description("Resume the latest persisted organization queue").option("--queue <pathOrFingerprint>", "Select a queue instead of the latest one").action(
|
|
16453
|
+
(_options, command) => runChatOrganizeResume(command.optsWithGlobals())
|
|
16454
|
+
);
|
|
15996
16455
|
const task = program.command("task").description("List or schedule ChatGPT Tasks (ChatGPT only)");
|
|
15997
16456
|
withWorkspaceFlags(task.command("list")).description("List ChatGPT Scheduled tasks").action(
|
|
15998
16457
|
(_options, command) => runTaskList(command.optsWithGlobals())
|