@codexhost/cli-darwin-x64 0.13.2 → 0.14.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 +1 -1
- package/app/codexhost-distribution.json +1 -1
- package/app/console-server.mjs +94 -8
- package/app/console-web.js +537 -146
- package/app/desktop-controller.mjs +108 -12
- package/app/host-runtime.mjs +847 -235
- package/app/plugins/antigravity/plugin.mjs +143 -20
- package/app/plugins/claude-code/plugin.mjs +601 -71
- package/app/plugins/codebuddy/plugin.mjs +227 -30
- package/app/plugins/codex-usage/plugin.mjs +212 -77
- package/app/plugins/copilot/assets/icon.png +0 -0
- package/app/plugins/copilot/manifest.json +26 -0
- package/app/plugins/copilot/plugin.mjs +34546 -0
- package/app/plugins/cursor-cli/plugin.mjs +20805 -44862
- package/app/plugins/deepseek-harness/manifest.json +2 -2
- package/app/plugins/deepseek-harness/plugin.mjs +202 -21
- package/app/plugins/enabled.json +1 -0
- package/app/plugins/grok/plugin.mjs +278 -29
- package/app/plugins/hermes/plugin.mjs +143 -12
- package/app/plugins/kimi-code/plugin.mjs +140 -16
- package/app/plugins/kiro-cli/plugin.mjs +121 -10
- package/app/plugins/omp/plugin.mjs +2200 -2002
- package/app/plugins/opencode/plugin.mjs +137 -16
- package/app/plugins/pi/plugin.mjs +2563 -2282
- package/app/plugins/qoder/plugin.mjs +133 -14
- package/app/plugins/qoder-cn/plugin.mjs +133 -14
- package/app/plugins/workbuddy/plugin.mjs +603 -56
- package/app/plugins/zcode/plugin.mjs +133 -14
- package/app/renderer-extension.js +1171 -529
- package/bin/codexhost +0 -0
- package/libexec/codexhost-shim +0 -0
- package/libexec/codexhost-updater +0 -0
- package/package.json +1 -1
package/app/host-runtime.mjs
CHANGED
|
@@ -3716,8 +3716,10 @@ List Harnesses available in the active Runtime.`,
|
|
|
3716
3716
|
"harness inspect": `codexhost harness inspect <harness> [--cwd <path>] [--refresh true|false] [--format json|compact]
|
|
3717
3717
|
Read available Models, native defaults, Thinking options, and configuration capabilities.
|
|
3718
3718
|
Use the returned Model and Thinking IDs for explicit selections.`,
|
|
3719
|
-
"delegate start": `codexhost delegate start --harness <id> --task <text> [--cwd <path>] [--model <opaque-ref>] [--thinking <option-id>] [--parent-thread <thread>] [--request-id <id>] [--watch true|false] [--watch-timeout-ms <n>] [--format json|compact]
|
|
3719
|
+
"delegate start": `codexhost delegate start --harness <id> --task <text> [--task-name <name>] [--cwd <path>] [--model <opaque-ref>] [--thinking <option-id>] [--parent-thread <thread>] [--request-id <id>] [--watch true|false] [--watch-timeout-ms <n>] [--format json|compact]
|
|
3720
3720
|
Create an independent child Thread, submit the task, and return immediately.
|
|
3721
|
+
--task-name supplies a short subtask name (1-120 characters); otherwise the first task line is used.
|
|
3722
|
+
The child title is "subtask name · parent title", fixed at creation; renaming the parent does not rename existing children.
|
|
3721
3723
|
Omit --model and --thinking to use the Harness native defaults.
|
|
3722
3724
|
--cwd overrides the child workspace. Otherwise use the resolved parent Thread workspace, then the Host Runtime process cwd.
|
|
3723
3725
|
--parent-thread overrides caller inference. PARENT_THREAD_AMBIGUOUS requires an explicit parent.
|
|
@@ -4161,6 +4163,7 @@ async function runDelegationCli(input) {
|
|
|
4161
4163
|
rejectUnknown(parsed2, [
|
|
4162
4164
|
"--harness",
|
|
4163
4165
|
"--task",
|
|
4166
|
+
"--task-name",
|
|
4164
4167
|
"--cwd",
|
|
4165
4168
|
"--model",
|
|
4166
4169
|
"--thinking",
|
|
@@ -4195,6 +4198,7 @@ async function runDelegationCli(input) {
|
|
|
4195
4198
|
body: {
|
|
4196
4199
|
harnessId,
|
|
4197
4200
|
task,
|
|
4201
|
+
...value(parsed2, "--task-name") !== void 0 ? { taskName: value(parsed2, "--task-name") } : {},
|
|
4198
4202
|
...value(parsed2, "--cwd") ? { cwd: value(parsed2, "--cwd") } : {},
|
|
4199
4203
|
...value(parsed2, "--model") ? { model: { id: value(parsed2, "--model") } } : {},
|
|
4200
4204
|
...value(parsed2, "--thinking") ? { thinkingOptionId: value(parsed2, "--thinking") } : {},
|
|
@@ -20027,6 +20031,15 @@ var harnessDisplaySetSchema = external_exports.strictObject({
|
|
|
20027
20031
|
initializeOnly: external_exports.boolean().optional()
|
|
20028
20032
|
});
|
|
20029
20033
|
|
|
20034
|
+
// packages/shared-contracts/dist/harness-presentation.js
|
|
20035
|
+
var localeSchema = external_exports.string().max(64).regex(/^[a-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/u);
|
|
20036
|
+
var displayText = (maximum) => external_exports.string().min(1).max(maximum).refine((text) => text.trim().length > 0);
|
|
20037
|
+
var harnessLocalizationsSchema = external_exports.record(localeSchema, external_exports.object({
|
|
20038
|
+
label: displayText(256).optional(),
|
|
20039
|
+
description: displayText(1024).optional()
|
|
20040
|
+
}).strict()).refine((entries) => Object.keys(entries).length <= 16, "Too many locales");
|
|
20041
|
+
var harnessLocalizedTextSchema = external_exports.record(localeSchema, displayText(4096)).refine((entries) => typeof entries.en === "string", "English fallback is required").refine((entries) => Object.keys(entries).length <= 16, "Too many locales");
|
|
20042
|
+
|
|
20030
20043
|
// packages/shared-contracts/dist/model-price-overrides.js
|
|
20031
20044
|
var MODEL_PRICE_OVERRIDES_GET_METHOD = "codexhost/usage/model-prices/get";
|
|
20032
20045
|
var MODEL_PRICE_OVERRIDES_SET_METHOD = "codexhost/usage/model-prices/set";
|
|
@@ -20080,10 +20093,19 @@ var model = external_exports.string().min(1).max(512);
|
|
|
20080
20093
|
var project = external_exports.string().min(1).max(4096);
|
|
20081
20094
|
var usageStatisticsParamsSchema = external_exports.strictObject({
|
|
20082
20095
|
range: external_exports.enum(USAGE_STATISTICS_RANGES),
|
|
20096
|
+
/** Display timezone for ranges, dates and hourly buckets; omitted means the Host's local zone. */
|
|
20097
|
+
timeZone: external_exports.string().min(1).max(128).refine((value2) => {
|
|
20098
|
+
try {
|
|
20099
|
+
new Intl.DateTimeFormat("en", { timeZone: value2 });
|
|
20100
|
+
return true;
|
|
20101
|
+
} catch {
|
|
20102
|
+
return false;
|
|
20103
|
+
}
|
|
20104
|
+
}, "Unsupported usage statistics timezone").optional(),
|
|
20083
20105
|
harness: harness.optional(),
|
|
20084
20106
|
model: model.nullable().optional(),
|
|
20085
20107
|
project: project.nullable().optional(),
|
|
20086
|
-
/** One
|
|
20108
|
+
/** One date in the query timezone inside the range. */
|
|
20087
20109
|
date: localDate.optional()
|
|
20088
20110
|
});
|
|
20089
20111
|
var usageStatisticsTotalsSchema = external_exports.strictObject({
|
|
@@ -20119,7 +20141,7 @@ var usageStatisticsSessionSchema = external_exports.strictObject({
|
|
|
20119
20141
|
});
|
|
20120
20142
|
var usageStatisticsResultSchema = external_exports.strictObject({
|
|
20121
20143
|
range: external_exports.enum(USAGE_STATISTICS_RANGES),
|
|
20122
|
-
/** First
|
|
20144
|
+
/** First date in the query timezone (Host local when omitted); null for all time. */
|
|
20123
20145
|
from: localDate.nullable(),
|
|
20124
20146
|
to: localDate,
|
|
20125
20147
|
/** The filters these figures apply, echoed so a late answer to older filters is recognised. */
|
|
@@ -20159,7 +20181,7 @@ var usageStatisticsResultSchema = external_exports.strictObject({
|
|
|
20159
20181
|
totals: usageStatisticsTotalsSchema,
|
|
20160
20182
|
/** Each date and Harness of the range: every filter except the day. */
|
|
20161
20183
|
daily: external_exports.array(external_exports.strictObject({ date: localDate, harness, ...totals })).max(2e5),
|
|
20162
|
-
/**
|
|
20184
|
+
/** Weekday (0 = Sunday) and hour in the query timezone, all filters applied. */
|
|
20163
20185
|
hourly: external_exports.array(external_exports.strictObject({
|
|
20164
20186
|
weekday: external_exports.number().int().min(0).max(6),
|
|
20165
20187
|
hour: external_exports.number().int().min(0).max(23),
|
|
@@ -20222,6 +20244,8 @@ var CONSOLE_HOST_METHODS = Object.freeze([
|
|
|
20222
20244
|
"codexhost/harness/display-settings/set",
|
|
20223
20245
|
"codexhost/harness/inspect",
|
|
20224
20246
|
"codexhost/harness/installation",
|
|
20247
|
+
"codexhost/harness/installation/start",
|
|
20248
|
+
"codexhost/harness/installation/status",
|
|
20225
20249
|
"codexhost/harness/launch-settings/get",
|
|
20226
20250
|
"codexhost/harness/launch-settings/set",
|
|
20227
20251
|
"codexhost/harness/web-ui/open",
|
|
@@ -20303,7 +20327,18 @@ var threadManualCompactionStartedSchema = external_exports.strictObject({
|
|
|
20303
20327
|
var nonNegativeSafeIntegerSchema = external_exports.number().int().safe().nonnegative();
|
|
20304
20328
|
var finiteNonNegativeNumberSchema = external_exports.number().finite().nonnegative();
|
|
20305
20329
|
var cacheHitRatePercentSchema = external_exports.number().finite().min(0).max(100);
|
|
20330
|
+
var indicatorTextSchema = (maximum) => harnessLocalizedTextSchema.refine((entries) => Object.values(entries).every((text) => text.length <= maximum));
|
|
20331
|
+
var composerIndicatorsSchema = external_exports.array(external_exports.object({
|
|
20332
|
+
kind: external_exports.literal("countdown"),
|
|
20333
|
+
id: external_exports.string().min(1).max(64),
|
|
20334
|
+
expiresAtUnix: nonNegativeSafeIntegerSchema,
|
|
20335
|
+
label: indicatorTextSchema(256).optional(),
|
|
20336
|
+
tooltip: indicatorTextSchema(1024).optional()
|
|
20337
|
+
}).strict()).max(2).refine((entries) => new Set(entries.map(({ id: id2 }) => id2)).size === entries.length, {
|
|
20338
|
+
message: "Composer indicator IDs must be unique"
|
|
20339
|
+
});
|
|
20306
20340
|
var threadUsageSnapshotSchema = external_exports.object({
|
|
20341
|
+
composerIndicators: composerIndicatorsSchema.optional(),
|
|
20307
20342
|
inputTokens: nonNegativeSafeIntegerSchema.optional(),
|
|
20308
20343
|
cachedInputTokens: nonNegativeSafeIntegerSchema.optional(),
|
|
20309
20344
|
cacheWriteInputTokens: nonNegativeSafeIntegerSchema.optional(),
|
|
@@ -20376,8 +20411,24 @@ var threadUsageSnapshotSchema = external_exports.object({
|
|
|
20376
20411
|
}
|
|
20377
20412
|
});
|
|
20378
20413
|
var usagePercentSchema = external_exports.number().finite().min(0).max(100);
|
|
20414
|
+
var accountCreditsPeriodSchema = external_exports.enum([
|
|
20415
|
+
"weekly",
|
|
20416
|
+
"monthly",
|
|
20417
|
+
"five_hour",
|
|
20418
|
+
"seven_day",
|
|
20419
|
+
"unknown"
|
|
20420
|
+
]);
|
|
20421
|
+
var accountCreditsScopeSchema = external_exports.object({
|
|
20422
|
+
id: external_exports.string().min(1).max(256),
|
|
20423
|
+
label: external_exports.string().min(1).max(256),
|
|
20424
|
+
localizations: harnessLocalizationsSchema.optional()
|
|
20425
|
+
}).strict();
|
|
20379
20426
|
var accountCreditsProductUsageSchema = external_exports.object({
|
|
20380
20427
|
product: external_exports.string().min(1),
|
|
20428
|
+
/** Native period and scope, never inferred from the display name. */
|
|
20429
|
+
periodType: accountCreditsPeriodSchema.optional(),
|
|
20430
|
+
scope: accountCreditsScopeSchema.optional(),
|
|
20431
|
+
localizations: harnessLocalizationsSchema.optional(),
|
|
20381
20432
|
used: external_exports.number().finite().nonnegative().optional(),
|
|
20382
20433
|
// Zero is a real empty cap, not an absent field.
|
|
20383
20434
|
limit: external_exports.number().finite().nonnegative().optional(),
|
|
@@ -20397,9 +20448,11 @@ var accountCreditsSnapshotSchema = external_exports.object({
|
|
|
20397
20448
|
unit: external_exports.string().min(1).max(32).optional(),
|
|
20398
20449
|
/** Native label when the primary limit is scoped to a model or product group. */
|
|
20399
20450
|
label: external_exports.string().min(1).optional(),
|
|
20451
|
+
scope: accountCreditsScopeSchema.optional(),
|
|
20452
|
+
localizations: harnessLocalizationsSchema.optional(),
|
|
20400
20453
|
usedPercent: usagePercentSchema,
|
|
20401
20454
|
resetsAt: external_exports.string().min(1).optional(),
|
|
20402
|
-
periodType:
|
|
20455
|
+
periodType: accountCreditsPeriodSchema,
|
|
20403
20456
|
productUsage: external_exports.array(accountCreditsProductUsageSchema).min(1).optional(),
|
|
20404
20457
|
resetCredits: accountResetCreditsSchema.optional()
|
|
20405
20458
|
}).strict();
|
|
@@ -20410,7 +20463,9 @@ var threadUsageInspectionParamsSchema = external_exports.object({
|
|
|
20410
20463
|
var threadUsageInspectionSchema = external_exports.object({
|
|
20411
20464
|
threadId: hostThreadIdSchema,
|
|
20412
20465
|
usage: threadUsageSnapshotSchema.nullable(),
|
|
20413
|
-
accountCredits: accountCreditsSnapshotSchema.optional()
|
|
20466
|
+
accountCredits: accountCreditsSnapshotSchema.optional(),
|
|
20467
|
+
/** Whether this source can provide cached account quota independently of usage. */
|
|
20468
|
+
accountCreditsSupported: external_exports.boolean().optional()
|
|
20414
20469
|
}).strict();
|
|
20415
20470
|
|
|
20416
20471
|
// packages/shared-contracts/dist/harness-accounts.js
|
|
@@ -20537,7 +20592,8 @@ var harnessPermissionModeSchema = external_exports.object({
|
|
|
20537
20592
|
id: harnessPermissionModeIdSchema,
|
|
20538
20593
|
label: nonBlankTextSchema.max(HARNESS_PERMISSION_MODE_LABEL_MAX_LENGTH),
|
|
20539
20594
|
description: nonBlankTextSchema.max(HARNESS_PERMISSION_MODE_DESCRIPTION_MAX_LENGTH).optional(),
|
|
20540
|
-
dangerous: external_exports.boolean().optional()
|
|
20595
|
+
dangerous: external_exports.boolean().optional(),
|
|
20596
|
+
localizations: harnessLocalizationsSchema.optional()
|
|
20541
20597
|
}).strict();
|
|
20542
20598
|
var harnessPermissionModeCatalogSchema = external_exports.object({
|
|
20543
20599
|
modes: external_exports.array(harnessPermissionModeSchema).min(1).max(HARNESS_PERMISSION_MODE_CATALOG_MAX_LENGTH),
|
|
@@ -20698,7 +20754,9 @@ var harnessSessionCapabilitiesSchema = external_exports.object({
|
|
|
20698
20754
|
}).strict().optional(),
|
|
20699
20755
|
autonomousTurns: external_exports.object({
|
|
20700
20756
|
observe: external_exports.boolean()
|
|
20701
|
-
}).strict().optional()
|
|
20757
|
+
}).strict().optional(),
|
|
20758
|
+
/** True only when `turn.steer` delivers input into the active Turn through a native primitive. */
|
|
20759
|
+
steer: external_exports.boolean().optional()
|
|
20702
20760
|
}).strict();
|
|
20703
20761
|
var harnessConfigurationStateSchema = external_exports.object({
|
|
20704
20762
|
effectiveModel: harnessModelRefSchema.optional(),
|
|
@@ -20746,7 +20804,9 @@ var harnessInspectionSchema = external_exports.union([
|
|
|
20746
20804
|
var harnessInspectParamsSchema = external_exports.object({
|
|
20747
20805
|
harnessId: harnessIdSchema,
|
|
20748
20806
|
cwd: nonBlankTextSchema2.max(16384).optional(),
|
|
20749
|
-
refresh: external_exports.boolean().optional()
|
|
20807
|
+
refresh: external_exports.boolean().optional(),
|
|
20808
|
+
/** `availability` asks only whether the Harness can run; see `InspectHarnessInput.purpose`. */
|
|
20809
|
+
purpose: external_exports.literal("availability").optional()
|
|
20750
20810
|
}).strict();
|
|
20751
20811
|
var harnessWebUiOpenParamsSchema = external_exports.object({
|
|
20752
20812
|
harnessId: harnessIdSchema
|
|
@@ -20829,6 +20889,16 @@ var threadOwnershipListResultSchema = external_exports.object({
|
|
|
20829
20889
|
seen.add(thread.threadId);
|
|
20830
20890
|
}
|
|
20831
20891
|
});
|
|
20892
|
+
var threadSteeringInspectParamsSchema = external_exports.object({
|
|
20893
|
+
threadId: hostThreadIdSchema,
|
|
20894
|
+
/** The text about to be steered; a Harness command always stops and restarts. */
|
|
20895
|
+
text: external_exports.string().optional()
|
|
20896
|
+
}).strict();
|
|
20897
|
+
var THREAD_STEER_DELIVERY_PARAM = "codexhostSteerDelivery";
|
|
20898
|
+
var threadSteerDeliverySchema = external_exports.enum(["activeTurn", "newTurn"]);
|
|
20899
|
+
var threadSteeringInspectResultSchema = external_exports.object({
|
|
20900
|
+
delivery: external_exports.enum(["official", "activeTurn", "newTurn"])
|
|
20901
|
+
}).strict();
|
|
20832
20902
|
|
|
20833
20903
|
// packages/shared-contracts/dist/harness-plugins.js
|
|
20834
20904
|
var HARNESS_PLUGIN_API_VERSION = 1;
|
|
@@ -20949,6 +21019,8 @@ var harnessLaunchSettingsSchema = external_exports.object({
|
|
|
20949
21019
|
|
|
20950
21020
|
// packages/shared-contracts/dist/harness-installation.js
|
|
20951
21021
|
var HARNESS_INSTALLATION_METHOD = "codexhost/harness/installation";
|
|
21022
|
+
var HARNESS_INSTALLATION_START_METHOD = "codexhost/harness/installation/start";
|
|
21023
|
+
var HARNESS_INSTALLATION_STATUS_METHOD = "codexhost/harness/installation/status";
|
|
20952
21024
|
var harnessInstallationParamsSchema = external_exports.object({
|
|
20953
21025
|
harnessId: harnessIdSchema,
|
|
20954
21026
|
action: external_exports.enum(["check", "update", "install"])
|
|
@@ -20958,11 +21030,31 @@ var harnessInstallationStateSchema = external_exports.object({
|
|
|
20958
21030
|
latestVersion: external_exports.string().min(1).max(128),
|
|
20959
21031
|
updateAvailable: external_exports.boolean(),
|
|
20960
21032
|
canUpdate: external_exports.boolean(),
|
|
21033
|
+
/** Defaults to CLI; some Harnesses ship only inside a desktop application. */
|
|
21034
|
+
versionKind: external_exports.enum(["cli", "application"]).optional(),
|
|
21035
|
+
/** Official download opened by the user; does not imply an automatic installation. */
|
|
21036
|
+
manualUpdateUrl: external_exports.url().max(2048).refine((value2) => /^https:\/\/[^/?#@]+(?:[/?#]|$)/iu.test(value2), "Manual updates require a credential-free HTTPS URL").optional(),
|
|
20961
21037
|
// Adapter-owned diagnostic text; UI uses messageCode rather than displaying it verbatim.
|
|
20962
21038
|
message: external_exports.string().max(2048).optional(),
|
|
20963
21039
|
messageCode: external_exports.string().min(1).max(128).optional(),
|
|
21040
|
+
/** Safe plugin-owned explanation, distinct from raw diagnostic message. */
|
|
21041
|
+
notice: harnessLocalizedTextSchema.optional(),
|
|
20964
21042
|
latestVersionKind: external_exports.enum(["unknown", "tracking-branch"]).optional()
|
|
20965
21043
|
}).strict();
|
|
21044
|
+
var harnessInstallationTaskParamsSchema = external_exports.object({ taskId: external_exports.string().uuid() }).strict();
|
|
21045
|
+
var harnessInstallationTaskSchema = external_exports.discriminatedUnion("status", [
|
|
21046
|
+
external_exports.object({ taskId: external_exports.string().uuid(), status: external_exports.literal("running") }).strict(),
|
|
21047
|
+
external_exports.object({
|
|
21048
|
+
taskId: external_exports.string().uuid(),
|
|
21049
|
+
status: external_exports.literal("succeeded"),
|
|
21050
|
+
result: harnessInstallationStateSchema
|
|
21051
|
+
}).strict(),
|
|
21052
|
+
external_exports.object({
|
|
21053
|
+
taskId: external_exports.string().uuid(),
|
|
21054
|
+
status: external_exports.literal("failed"),
|
|
21055
|
+
error: external_exports.object({ code: external_exports.number().int(), message: external_exports.string().min(1).max(2048) }).strict()
|
|
21056
|
+
}).strict()
|
|
21057
|
+
]);
|
|
20966
21058
|
|
|
20967
21059
|
// packages/shared-contracts/dist/codex-accounts.js
|
|
20968
21060
|
var accountIdSchema = external_exports.string().min(1).max(256).regex(/^[A-Za-z0-9._~-]+$/u);
|
|
@@ -21091,6 +21183,7 @@ var harnessCommandDescriptorSchema = external_exports.object({
|
|
|
21091
21183
|
invocation: commandInvocationSchema,
|
|
21092
21184
|
label: commandLabelSchema,
|
|
21093
21185
|
description: commandDescriptionSchema.optional(),
|
|
21186
|
+
localizations: harnessLocalizationsSchema.optional(),
|
|
21094
21187
|
argumentMode: external_exports.enum(["none", "text"]),
|
|
21095
21188
|
/**
|
|
21096
21189
|
* Native distinction reported by the Harness. Omitted when the Harness does
|
|
@@ -21482,6 +21575,9 @@ var RuntimeMaintenance = class {
|
|
|
21482
21575
|
#watch = null;
|
|
21483
21576
|
#starting = null;
|
|
21484
21577
|
#startingVersion = null;
|
|
21578
|
+
get #startTimeoutMs() {
|
|
21579
|
+
return this.options.updaterStartTimeoutMs ?? UPDATER_START_TIMEOUT_MS;
|
|
21580
|
+
}
|
|
21485
21581
|
#ensureWatching() {
|
|
21486
21582
|
if (this.#watch) return;
|
|
21487
21583
|
this.#watch = setInterval(() => {
|
|
@@ -21578,7 +21674,7 @@ var RuntimeMaintenance = class {
|
|
|
21578
21674
|
}
|
|
21579
21675
|
} else {
|
|
21580
21676
|
const written = (await stat(this.#statusPath)).mtimeMs;
|
|
21581
|
-
alive = Date.now() - written <
|
|
21677
|
+
alive = Date.now() - written < this.#startTimeoutMs * 2;
|
|
21582
21678
|
}
|
|
21583
21679
|
if (!alive) {
|
|
21584
21680
|
parsed2.phase = "failed";
|
|
@@ -21702,7 +21798,7 @@ var RuntimeMaintenance = class {
|
|
|
21702
21798
|
if (!Number.isSafeInteger(helperPid) || helperPid <= 0) {
|
|
21703
21799
|
throw new Error("Remote updater could not be started");
|
|
21704
21800
|
}
|
|
21705
|
-
const deadline = Date.now() +
|
|
21801
|
+
const deadline = Date.now() + this.#startTimeoutMs;
|
|
21706
21802
|
while (!await this.#helperReported()) {
|
|
21707
21803
|
if (Date.now() >= deadline) {
|
|
21708
21804
|
try {
|
|
@@ -22946,9 +23042,13 @@ function requestManagerFromHookState(value2, hostId2) {
|
|
|
22946
23042
|
const direct = manager(value2) ?? manager(value2.manager);
|
|
22947
23043
|
if (direct)
|
|
22948
23044
|
return direct;
|
|
22949
|
-
if (!hostId2 || typeof value2.addManager !== "function" || typeof value2.getForHostId !== "function"
|
|
23045
|
+
if (!hostId2 || typeof value2.addManager !== "function" || typeof value2.getForHostId !== "function")
|
|
22950
23046
|
return null;
|
|
22951
|
-
|
|
23047
|
+
try {
|
|
23048
|
+
return manager(value2.getForHostId(hostId2));
|
|
23049
|
+
} catch {
|
|
23050
|
+
return null;
|
|
23051
|
+
}
|
|
22952
23052
|
}
|
|
22953
23053
|
function discoverRendererHosts(root, ancestors = committedReactAncestors, managerFrom = requestManagerFromHookState) {
|
|
22954
23054
|
const editors = [
|
|
@@ -22984,7 +23084,7 @@ function discoverRendererHosts(root, ancestors = committedReactAncestors, manage
|
|
|
22984
23084
|
const manager = managerFrom(value2);
|
|
22985
23085
|
if (manager)
|
|
22986
23086
|
managers.add(manager);
|
|
22987
|
-
if (value2 && typeof value2 === "object" && "addManager" in value2 && typeof value2.addManager === "function" && "getForHostId" in value2 && typeof value2.getForHostId === "function"
|
|
23087
|
+
if (value2 && typeof value2 === "object" && "addManager" in value2 && typeof value2.addManager === "function" && "getForHostId" in value2 && typeof value2.getForHostId === "function") {
|
|
22988
23088
|
registries.add(value2);
|
|
22989
23089
|
}
|
|
22990
23090
|
hook = hook.next && typeof hook.next === "object" ? hook.next : null;
|
|
@@ -23000,7 +23100,13 @@ function discoverRendererHosts(root, ancestors = committedReactAncestors, manage
|
|
|
23000
23100
|
function resolveRendererHostManager(discovery, hostId2, managerFrom = requestManagerFromHookState) {
|
|
23001
23101
|
if (!hostId2)
|
|
23002
23102
|
return null;
|
|
23003
|
-
const candidates = discovery.registries.length ? discovery.registries.
|
|
23103
|
+
const candidates = discovery.registries.length ? discovery.registries.flatMap((registry2) => {
|
|
23104
|
+
try {
|
|
23105
|
+
return [managerFrom(registry2.getForHostId(hostId2))];
|
|
23106
|
+
} catch {
|
|
23107
|
+
return [];
|
|
23108
|
+
}
|
|
23109
|
+
}) : discovery.managers;
|
|
23004
23110
|
const matching = new Set(candidates.filter((manager) => manager && (manager.getHostId?.() ?? manager.requestClient.hostId) === hostId2 && (manager.requestClient.hostId === void 0 || manager.requestClient.hostId === hostId2)));
|
|
23005
23111
|
return matching.size === 1 ? matching.values().next().value ?? null : null;
|
|
23006
23112
|
}
|
|
@@ -24012,6 +24118,64 @@ async function handleHarnessInstallation(params, adapters) {
|
|
|
24012
24118
|
}
|
|
24013
24119
|
}
|
|
24014
24120
|
|
|
24121
|
+
// packages/host-runtime/src/harness-installation-tasks.ts
|
|
24122
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
24123
|
+
var HarnessInstallationTasks = class {
|
|
24124
|
+
#tasks = /* @__PURE__ */ new Map();
|
|
24125
|
+
#active = /* @__PURE__ */ new Map();
|
|
24126
|
+
#prune() {
|
|
24127
|
+
const cutoff = Date.now() - 15 * 6e4;
|
|
24128
|
+
for (const [id2, task] of this.#tasks) {
|
|
24129
|
+
if (task.finishedAt !== void 0 && task.finishedAt < cutoff) this.#tasks.delete(id2);
|
|
24130
|
+
}
|
|
24131
|
+
}
|
|
24132
|
+
start(params, adapters) {
|
|
24133
|
+
const parsed2 = harnessInstallationParamsSchema.safeParse(params);
|
|
24134
|
+
if (!parsed2.success)
|
|
24135
|
+
throw new HarnessInstallationError(-32602, "Invalid Harness installation request");
|
|
24136
|
+
this.#prune();
|
|
24137
|
+
const key = JSON.stringify([parsed2.data.harnessId, parsed2.data.action]);
|
|
24138
|
+
const activeId = this.#active.get(key);
|
|
24139
|
+
const active = activeId ? this.#tasks.get(activeId) : void 0;
|
|
24140
|
+
if (active) return active.state;
|
|
24141
|
+
const taskId = randomUUID3();
|
|
24142
|
+
const task = {
|
|
24143
|
+
state: { taskId, status: "running" }
|
|
24144
|
+
};
|
|
24145
|
+
this.#tasks.set(taskId, task);
|
|
24146
|
+
this.#active.set(key, taskId);
|
|
24147
|
+
void handleHarnessInstallation(parsed2.data, adapters).then(
|
|
24148
|
+
(result) => {
|
|
24149
|
+
task.state = { taskId, status: "succeeded", result };
|
|
24150
|
+
},
|
|
24151
|
+
(error51) => {
|
|
24152
|
+
task.state = {
|
|
24153
|
+
taskId,
|
|
24154
|
+
status: "failed",
|
|
24155
|
+
error: error51 instanceof HarnessInstallationError ? { code: error51.code, message: error51.message } : { code: -32077, message: "Harness version management failed" }
|
|
24156
|
+
};
|
|
24157
|
+
}
|
|
24158
|
+
).finally(() => {
|
|
24159
|
+
task.finishedAt = Date.now();
|
|
24160
|
+
this.#active.delete(key);
|
|
24161
|
+
});
|
|
24162
|
+
return task.state;
|
|
24163
|
+
}
|
|
24164
|
+
status(params) {
|
|
24165
|
+
const parsed2 = harnessInstallationTaskParamsSchema.safeParse(params);
|
|
24166
|
+
if (!parsed2.success)
|
|
24167
|
+
throw new HarnessInstallationError(-32602, "Invalid Harness installation task request");
|
|
24168
|
+
this.#prune();
|
|
24169
|
+
const task = this.#tasks.get(parsed2.data.taskId);
|
|
24170
|
+
if (!task)
|
|
24171
|
+
throw new HarnessInstallationError(
|
|
24172
|
+
-32079,
|
|
24173
|
+
"Harness installation task is unavailable on this Host"
|
|
24174
|
+
);
|
|
24175
|
+
return task.state;
|
|
24176
|
+
}
|
|
24177
|
+
};
|
|
24178
|
+
|
|
24015
24179
|
// packages/host-runtime/src/account/codex-credential-export.ts
|
|
24016
24180
|
import { createHash as createHash3 } from "node:crypto";
|
|
24017
24181
|
import { readFile as readFile8 } from "node:fs/promises";
|
|
@@ -24104,7 +24268,7 @@ async function listOthers(adapter) {
|
|
|
24104
24268
|
}
|
|
24105
24269
|
|
|
24106
24270
|
// packages/host-runtime/src/harness-display-settings.ts
|
|
24107
|
-
import { randomUUID as
|
|
24271
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
24108
24272
|
import { link, mkdir as mkdir6, readFile as readFile9, rename as rename4, rm as rm5, writeFile as writeFile6 } from "node:fs/promises";
|
|
24109
24273
|
import os4 from "node:os";
|
|
24110
24274
|
import path13 from "node:path";
|
|
@@ -24129,7 +24293,7 @@ var HarnessDisplaySettingsStore = class {
|
|
|
24129
24293
|
async set(input) {
|
|
24130
24294
|
const entries = harnessDisplayEntriesSchema.parse(input.entries);
|
|
24131
24295
|
await mkdir6(path13.dirname(this.#file), { recursive: true, mode: 448 });
|
|
24132
|
-
const temporary = `${this.#file}.${
|
|
24296
|
+
const temporary = `${this.#file}.${randomUUID4()}.tmp`;
|
|
24133
24297
|
try {
|
|
24134
24298
|
await writeFile6(temporary, `${JSON.stringify(entries)}
|
|
24135
24299
|
`, { mode: 384, flag: "wx" });
|
|
@@ -24150,7 +24314,7 @@ var HarnessDisplaySettingsStore = class {
|
|
|
24150
24314
|
};
|
|
24151
24315
|
|
|
24152
24316
|
// packages/host-runtime/src/model-price-overrides-file.ts
|
|
24153
|
-
import { randomUUID as
|
|
24317
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
24154
24318
|
import { mkdir as mkdir8, readFile as readFile11, rename as rename6, rm as rm6, writeFile as writeFile8 } from "node:fs/promises";
|
|
24155
24319
|
import path15 from "node:path";
|
|
24156
24320
|
|
|
@@ -24725,7 +24889,7 @@ async function updateModelPriceOverridesFile(file2, change) {
|
|
|
24725
24889
|
const updated = { ...document, models: next };
|
|
24726
24890
|
parseModelPriceOverrides(updated);
|
|
24727
24891
|
await mkdir8(path15.dirname(file2), { recursive: true });
|
|
24728
|
-
const temporary = `${file2}.${
|
|
24892
|
+
const temporary = `${file2}.${randomUUID5()}.tmp`;
|
|
24729
24893
|
try {
|
|
24730
24894
|
await writeFile8(temporary, `${JSON.stringify(updated, null, 2)}
|
|
24731
24895
|
`, { flag: "wx" });
|
|
@@ -24761,11 +24925,11 @@ async function handleModelPriceOverridesRequest(catalog, method, params) {
|
|
|
24761
24925
|
}
|
|
24762
24926
|
|
|
24763
24927
|
// packages/host-runtime/src/delegation-skill.ts
|
|
24764
|
-
import { createHash as createHash4, randomUUID as
|
|
24928
|
+
import { createHash as createHash4, randomUUID as randomUUID6 } from "node:crypto";
|
|
24765
24929
|
import { mkdir as mkdir9, open as open4, readFile as readFile12, rename as rename7, rm as rm7, stat as stat5 } from "node:fs/promises";
|
|
24766
24930
|
import os6 from "node:os";
|
|
24767
24931
|
import path16 from "node:path";
|
|
24768
|
-
var SKILL_VERSION =
|
|
24932
|
+
var SKILL_VERSION = 10;
|
|
24769
24933
|
var DELEGATION_SKILL_NAME = "codexhost-delegation";
|
|
24770
24934
|
var SKILL_RELATIVE_PATH = path16.join("skills", DELEGATION_SKILL_NAME, "SKILL.md");
|
|
24771
24935
|
var PREVIOUS_MANAGED_DIGESTS = [
|
|
@@ -24779,7 +24943,9 @@ var PREVIOUS_MANAGED_DIGESTS = [
|
|
|
24779
24943
|
"fa7944cd1e72ffbaf932fca2074bdb78aad4670d8990b6711220dd83c39509a0",
|
|
24780
24944
|
"b9c1cce41d2556e73a6514aa55618d7d3f2f9ef935f5ae50b0da5a04941514b4",
|
|
24781
24945
|
// v8, which ran a bare `codexhost` from PATH.
|
|
24782
|
-
"ca06be59f0d47c9a54d05ed2d9588c9c737306cc155cb4dff3fe2a2a61891dde"
|
|
24946
|
+
"ca06be59f0d47c9a54d05ed2d9588c9c737306cc155cb4dff3fe2a2a61891dde",
|
|
24947
|
+
// v9, before the child-session name guidance.
|
|
24948
|
+
"b72a059e139bd5b93b95f7ac02ab80f428d5a721cc67b004210d5263e75baed7"
|
|
24783
24949
|
];
|
|
24784
24950
|
var CODEXHOST_DELEGATION_SKILL = `---
|
|
24785
24951
|
name: codexhost-delegation
|
|
@@ -24816,7 +24982,8 @@ Use the Harness native defaults. Inspect the target when a Model or Thinking
|
|
|
24816
24982
|
selection is needed or the default is unavailable.
|
|
24817
24983
|
|
|
24818
24984
|
For a new delegation, create an independent child session and submit the
|
|
24819
|
-
requested task.
|
|
24985
|
+
requested task. Give it a short task name that tells it apart from sibling
|
|
24986
|
+
tasks, using the help's task-name option. For an existing external session, resolve the target from the
|
|
24820
24987
|
user-provided session link, identifier, or context and operate on that Thread
|
|
24821
24988
|
directly; it need not have been created by the current assistant. If the target
|
|
24822
24989
|
is ambiguous, ask the user to identify it. Keep requests to view or summarize a
|
|
@@ -24858,7 +25025,7 @@ async function readOptional(filePath) {
|
|
|
24858
25025
|
}
|
|
24859
25026
|
async function atomicWrite(filePath, content) {
|
|
24860
25027
|
await mkdir9(path16.dirname(filePath), { recursive: true, mode: 448 });
|
|
24861
|
-
const temporaryPath = path16.join(path16.dirname(filePath), `.SKILL.md.${
|
|
25028
|
+
const temporaryPath = path16.join(path16.dirname(filePath), `.SKILL.md.${randomUUID6()}.tmp`);
|
|
24862
25029
|
const handle = await open4(temporaryPath, "wx", 384);
|
|
24863
25030
|
try {
|
|
24864
25031
|
await handle.writeFile(content, "utf8");
|
|
@@ -25003,6 +25170,16 @@ function rewriteDelegationMentionInput(input, skill) {
|
|
|
25003
25170
|
return rewritten;
|
|
25004
25171
|
}
|
|
25005
25172
|
|
|
25173
|
+
// packages/harness-adapter/dist/account-credits.js
|
|
25174
|
+
function parseHarnessAccountCredits(value2) {
|
|
25175
|
+
if (!value2 || typeof value2 !== "object" || Array.isArray(value2))
|
|
25176
|
+
return null;
|
|
25177
|
+
const publicValue = { ...value2 };
|
|
25178
|
+
delete publicValue.fetchedAt;
|
|
25179
|
+
const parsed2 = accountCreditsSnapshotSchema.safeParse(publicValue);
|
|
25180
|
+
return parsed2.success ? parsed2.data : null;
|
|
25181
|
+
}
|
|
25182
|
+
|
|
25006
25183
|
// packages/harness-adapter/dist/output-channel.js
|
|
25007
25184
|
var HarnessOutputChannel = class {
|
|
25008
25185
|
outputs;
|
|
@@ -25085,6 +25262,7 @@ var usageFields = /* @__PURE__ */ new Set([
|
|
|
25085
25262
|
...safeIntegerFields,
|
|
25086
25263
|
...percentFields,
|
|
25087
25264
|
"sessionCacheUsage",
|
|
25265
|
+
"composerIndicators",
|
|
25088
25266
|
"totalCostUsd",
|
|
25089
25267
|
"totalCredits",
|
|
25090
25268
|
"contextUsagePercent",
|
|
@@ -25107,6 +25285,7 @@ function parseHostUsage(value2) {
|
|
|
25107
25285
|
throw new Error(`Harness Usage contains unknown field '${key}'`);
|
|
25108
25286
|
}
|
|
25109
25287
|
}
|
|
25288
|
+
const indicators = value2.composerIndicators === void 0 ? {} : { composerIndicators: composerIndicatorsSchema.parse(value2.composerIndicators) };
|
|
25110
25289
|
for (const field of [
|
|
25111
25290
|
"totalCredits",
|
|
25112
25291
|
"contextUsagePercent",
|
|
@@ -25177,9 +25356,9 @@ function parseHostUsage(value2) {
|
|
|
25177
25356
|
if (value2.costSource !== "publicPrice") {
|
|
25178
25357
|
throw new Error("Harness Usage 'unpricedModels' must be provided with a 'publicPrice' cost");
|
|
25179
25358
|
}
|
|
25180
|
-
return { ...value2, unpricedModels: [...models] };
|
|
25359
|
+
return { ...value2, ...indicators, unpricedModels: [...models] };
|
|
25181
25360
|
}
|
|
25182
|
-
return { ...value2 };
|
|
25361
|
+
return { ...value2, ...indicators };
|
|
25183
25362
|
}
|
|
25184
25363
|
var requestTokenFields = [
|
|
25185
25364
|
"inputTokens",
|
|
@@ -25330,7 +25509,7 @@ var packageMetadata = {
|
|
|
25330
25509
|
|
|
25331
25510
|
// packages/mapping-store/dist/mapping-store.js
|
|
25332
25511
|
import { execFileSync } from "node:child_process";
|
|
25333
|
-
import { randomUUID as
|
|
25512
|
+
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
25334
25513
|
import { constants as constants3 } from "node:fs";
|
|
25335
25514
|
import { copyFile as copyFile3, mkdir as mkdir11, open as open7, readFile as readFile15, readdir as readdir4, rename as rename10, rm as rm10, stat as stat6 } from "node:fs/promises";
|
|
25336
25515
|
import path18 from "node:path";
|
|
@@ -25390,7 +25569,7 @@ var storedThreadMetadataV1Schema = external_exports.object({
|
|
|
25390
25569
|
formatVersion: external_exports.literal(1),
|
|
25391
25570
|
hostThreadId: storedHostThreadIdSchema,
|
|
25392
25571
|
...storedThreadMetadataFieldsShape
|
|
25393
|
-
}).
|
|
25572
|
+
}).passthrough();
|
|
25394
25573
|
function refineThreadRecord(record4, context) {
|
|
25395
25574
|
if (record4.state === "ready" && !record4.nativeSessionRef) {
|
|
25396
25575
|
context.addIssue({
|
|
@@ -25449,8 +25628,8 @@ function refineThreadRecord(record4, context) {
|
|
|
25449
25628
|
}
|
|
25450
25629
|
}
|
|
25451
25630
|
}
|
|
25452
|
-
var storedThreadCoreV1Schema = external_exports.object(storedThreadCoreV1Shape).
|
|
25453
|
-
var storedThreadRecordV1Schema = external_exports.object({ ...storedThreadCoreV1Shape, ...storedThreadMetadataFieldsShape }).
|
|
25631
|
+
var storedThreadCoreV1Schema = external_exports.object(storedThreadCoreV1Shape).passthrough().superRefine(refineThreadRecord);
|
|
25632
|
+
var storedThreadRecordV1Schema = external_exports.object({ ...storedThreadCoreV1Shape, ...storedThreadMetadataFieldsShape }).passthrough().superRefine(refineThreadRecord);
|
|
25454
25633
|
var delegationStatusSchema = external_exports.enum([
|
|
25455
25634
|
"creating",
|
|
25456
25635
|
"running",
|
|
@@ -25477,7 +25656,7 @@ var storedDelegationRecordV1Schema = external_exports.object({
|
|
|
25477
25656
|
});
|
|
25478
25657
|
|
|
25479
25658
|
// packages/mapping-store/dist/section-placements.js
|
|
25480
|
-
import { randomUUID as
|
|
25659
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
25481
25660
|
import { constants } from "node:fs";
|
|
25482
25661
|
import { open as open5, readFile as readFile13, rename as rename8, rm as rm8 } from "node:fs/promises";
|
|
25483
25662
|
var threadIdSchema = external_exports.string().min(1).max(1024);
|
|
@@ -25529,7 +25708,7 @@ async function readSectionPlacementsFile(file2) {
|
|
|
25529
25708
|
}
|
|
25530
25709
|
async function writeSectionPlacementsFile(file2, placements) {
|
|
25531
25710
|
const parsed2 = parseSectionPlacements({ formatVersion: 1, placements });
|
|
25532
|
-
const temp = `${file2}.tmp-${
|
|
25711
|
+
const temp = `${file2}.tmp-${randomUUID7()}`;
|
|
25533
25712
|
let handle = null;
|
|
25534
25713
|
try {
|
|
25535
25714
|
handle = await open5(temp, "wx", constants.S_IRUSR | constants.S_IWUSR);
|
|
@@ -25548,7 +25727,7 @@ async function writeSectionPlacementsFile(file2, placements) {
|
|
|
25548
25727
|
}
|
|
25549
25728
|
|
|
25550
25729
|
// packages/mapping-store/dist/superseded-sessions.js
|
|
25551
|
-
import { randomUUID as
|
|
25730
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
25552
25731
|
import { constants as constants2 } from "node:fs";
|
|
25553
25732
|
import { mkdir as mkdir10, open as open6, readFile as readFile14, rename as rename9, rm as rm9 } from "node:fs/promises";
|
|
25554
25733
|
import path17 from "node:path";
|
|
@@ -25583,7 +25762,7 @@ async function writeSupersededSessionsFile(file2, sessions) {
|
|
|
25583
25762
|
formatVersion: 1,
|
|
25584
25763
|
sessions: sessions.slice(-SUPERSEDED_SESSIONS_MAX)
|
|
25585
25764
|
}).sessions;
|
|
25586
|
-
const temp = `${file2}.tmp-${
|
|
25765
|
+
const temp = `${file2}.tmp-${randomUUID8()}`;
|
|
25587
25766
|
let handle = null;
|
|
25588
25767
|
try {
|
|
25589
25768
|
await mkdir10(path17.dirname(file2), { recursive: true });
|
|
@@ -25828,7 +26007,7 @@ var MappingStore = class {
|
|
|
25828
26007
|
this.#sectionsDirectory = path18.join(this.#directory, "sections");
|
|
25829
26008
|
this.#metadataDirectory = path18.join(this.#directory, "thread-metadata");
|
|
25830
26009
|
this.#lockPath = path18.join(this.#directory, "store.lock");
|
|
25831
|
-
this.#instanceId = options2.instanceId ??
|
|
26010
|
+
this.#instanceId = options2.instanceId ?? randomUUID9();
|
|
25832
26011
|
this.#now = options2.now ?? (() => /* @__PURE__ */ new Date());
|
|
25833
26012
|
this.#beforeReplace = options2.beforeReplace;
|
|
25834
26013
|
}
|
|
@@ -26352,7 +26531,7 @@ var MappingStore = class {
|
|
|
26352
26531
|
this.#rebuildIndexes();
|
|
26353
26532
|
}
|
|
26354
26533
|
async #replaceFile(target, record4, preserveBackup) {
|
|
26355
|
-
const temp = `${target}.tmp-${
|
|
26534
|
+
const temp = `${target}.tmp-${randomUUID9()}`;
|
|
26356
26535
|
let handle = null;
|
|
26357
26536
|
try {
|
|
26358
26537
|
await this.#beforeReplace?.(cloneRecord(record4));
|
|
@@ -26376,18 +26555,20 @@ var MappingStore = class {
|
|
|
26376
26555
|
});
|
|
26377
26556
|
}
|
|
26378
26557
|
}
|
|
26379
|
-
/** Atomically
|
|
26558
|
+
/** Atomically patches owned metadata fields, retaining unknown fields on disk. */
|
|
26380
26559
|
async #writeMetadataFile(hostThreadId, metadata) {
|
|
26381
26560
|
const target = this.#metadataPath(hostThreadId);
|
|
26382
|
-
const temp = `${target}.tmp-${
|
|
26561
|
+
const temp = `${target}.tmp-${randomUUID9()}`;
|
|
26383
26562
|
let handle = null;
|
|
26384
26563
|
try {
|
|
26385
|
-
|
|
26564
|
+
const retained = Object.fromEntries(Object.entries(await this.#readMetadata(hostThreadId) ?? {}).filter(([name]) => !["formatVersion", "hostThreadId", ...THREAD_METADATA_FIELDS].includes(name)));
|
|
26565
|
+
if (!metadata && Object.keys(retained).length === 0) {
|
|
26386
26566
|
await rm10(target, { force: true });
|
|
26387
26567
|
return;
|
|
26388
26568
|
}
|
|
26569
|
+
const next = { ...retained, formatVersion: 1, hostThreadId, ...metadata };
|
|
26389
26570
|
handle = await open7(temp, "wx", constants3.S_IRUSR | constants3.S_IWUSR);
|
|
26390
|
-
await handle.writeFile(`${JSON.stringify(
|
|
26571
|
+
await handle.writeFile(`${JSON.stringify(next, null, 2)}
|
|
26391
26572
|
`, "utf8");
|
|
26392
26573
|
await handle.sync();
|
|
26393
26574
|
await handle.close();
|
|
@@ -26424,7 +26605,7 @@ var MappingStore = class {
|
|
|
26424
26605
|
}
|
|
26425
26606
|
async #replaceDelegationFile(record4) {
|
|
26426
26607
|
const target = this.#delegationPath(record4.delegationId);
|
|
26427
|
-
const temp = `${target}.tmp-${
|
|
26608
|
+
const temp = `${target}.tmp-${randomUUID9()}`;
|
|
26428
26609
|
let handle = null;
|
|
26429
26610
|
try {
|
|
26430
26611
|
handle = await open7(temp, "wx", constants3.S_IRUSR | constants3.S_IWUSR);
|
|
@@ -27102,6 +27283,7 @@ function projectCodexRateLimitsToCredits(usage, resetCredits) {
|
|
|
27102
27283
|
const resetsAtUnix = hasFiveHour ? usage.planFiveHourResetsAtUnix : usage.planSevenDayResetsAtUnix;
|
|
27103
27284
|
const secondary = hasFiveHour && hasSevenDay && usage.planSevenDayUsedPercent !== void 0 ? {
|
|
27104
27285
|
product: "7-day window",
|
|
27286
|
+
periodType: "seven_day",
|
|
27105
27287
|
usagePercent: usage.planSevenDayUsedPercent,
|
|
27106
27288
|
...usage.planSevenDayResetsAtUnix !== void 0 ? { resetsAt: isoFromUnix(usage.planSevenDayResetsAtUnix) } : {}
|
|
27107
27289
|
} : void 0;
|
|
@@ -28108,8 +28290,18 @@ function collabAgentStatus(status2) {
|
|
|
28108
28290
|
return "interrupted";
|
|
28109
28291
|
}
|
|
28110
28292
|
}
|
|
28293
|
+
function projectUserMessage(item, clientId) {
|
|
28294
|
+
return {
|
|
28295
|
+
id: item.itemId,
|
|
28296
|
+
type: "userMessage",
|
|
28297
|
+
clientId,
|
|
28298
|
+
content: item.input.map(({ text }) => ({ type: "text", text, text_elements: [] }))
|
|
28299
|
+
};
|
|
28300
|
+
}
|
|
28111
28301
|
function projectItem(item, outcome, defaultCwd, includeCommandOutput = true, senderThreadId) {
|
|
28112
28302
|
switch (item.type) {
|
|
28303
|
+
case "userMessage":
|
|
28304
|
+
return projectUserMessage(item, null);
|
|
28113
28305
|
case "agentMessage":
|
|
28114
28306
|
return {
|
|
28115
28307
|
id: item.itemId,
|
|
@@ -28321,6 +28513,7 @@ var CodexTurnProjector = class {
|
|
|
28321
28513
|
#interactions = /* @__PURE__ */ new Map();
|
|
28322
28514
|
#items = /* @__PURE__ */ new Map();
|
|
28323
28515
|
#wireItemOrder = [];
|
|
28516
|
+
#userMessageClientIds = /* @__PURE__ */ new Map();
|
|
28324
28517
|
#startedAt;
|
|
28325
28518
|
#startedAtMs;
|
|
28326
28519
|
#threadId;
|
|
@@ -28362,6 +28555,10 @@ var CodexTurnProjector = class {
|
|
|
28362
28555
|
}
|
|
28363
28556
|
return items;
|
|
28364
28557
|
}
|
|
28558
|
+
/** Associate steered input with the Desktop message that submitted it, before it is published. */
|
|
28559
|
+
bindUserMessageClientId(itemId, clientId) {
|
|
28560
|
+
this.#userMessageClientIds.set(itemId, clientId);
|
|
28561
|
+
}
|
|
28365
28562
|
pendingTurn(startedAt = null) {
|
|
28366
28563
|
return {
|
|
28367
28564
|
id: this.#turnId,
|
|
@@ -28372,6 +28569,8 @@ var CodexTurnProjector = class {
|
|
|
28372
28569
|
const projected = this.#items.get(itemId);
|
|
28373
28570
|
if (!projected?.wireStarted)
|
|
28374
28571
|
return [];
|
|
28572
|
+
if (projected.item.type === "userMessage")
|
|
28573
|
+
return [this.#projectItem(projected.item)];
|
|
28375
28574
|
if (projected.item.type === "agentMessage") {
|
|
28376
28575
|
return [projectItem(projected.item, projected.outcome, this.#cwd)];
|
|
28377
28576
|
}
|
|
@@ -28699,7 +28898,7 @@ var CodexTurnProjector = class {
|
|
|
28699
28898
|
return { messages: [] };
|
|
28700
28899
|
}
|
|
28701
28900
|
const messages = [
|
|
28702
|
-
completedItem(projectItem(projected.item, projected.outcome,
|
|
28901
|
+
completedItem(this.#projectItem(projected.item, projected.outcome, !projected.streamedCommandOutput))
|
|
28703
28902
|
];
|
|
28704
28903
|
if (projected.item.type === "reasoning") {
|
|
28705
28904
|
const reasoning = projected.item;
|
|
@@ -28764,6 +28963,8 @@ var CodexTurnProjector = class {
|
|
|
28764
28963
|
projectReasoningTranscriptItem(reasoning, projected.outcome, this.#cwd, projected.durationMs ?? null)
|
|
28765
28964
|
];
|
|
28766
28965
|
}
|
|
28966
|
+
if (projected.item.type === "userMessage")
|
|
28967
|
+
return [this.#projectItem(projected.item)];
|
|
28767
28968
|
if (projected.item.type === "agentMessage") {
|
|
28768
28969
|
return [projectItem(projected.item, projected.outcome, this.#cwd)];
|
|
28769
28970
|
}
|
|
@@ -28849,10 +29050,13 @@ var CodexTurnProjector = class {
|
|
|
28849
29050
|
threadId: this.#threadId,
|
|
28850
29051
|
turnId: this.#turnId,
|
|
28851
29052
|
startedAtMs,
|
|
28852
|
-
item: projectItem(item, null
|
|
29053
|
+
item: this.#projectItem(item, null)
|
|
28853
29054
|
}
|
|
28854
29055
|
};
|
|
28855
29056
|
}
|
|
29057
|
+
#projectItem(item, outcome = null, includeCommandOutput = true) {
|
|
29058
|
+
return item.type === "userMessage" ? projectUserMessage(item, this.#userMessageClientIds.get(item.itemId) ?? null) : projectItem(item, outcome, this.#cwd, includeCommandOutput, this.#threadId);
|
|
29059
|
+
}
|
|
28856
29060
|
#startReasoningTranscript(item, startedAtMs) {
|
|
28857
29061
|
return {
|
|
28858
29062
|
method: "item/started",
|
|
@@ -30244,7 +30448,7 @@ var HarnessAccountInspectionCache = class {
|
|
|
30244
30448
|
};
|
|
30245
30449
|
|
|
30246
30450
|
// packages/host-runtime/src/app-server-host.ts
|
|
30247
|
-
import { createHash as createHash9, randomUUID as
|
|
30451
|
+
import { createHash as createHash9, randomUUID as randomUUID16 } from "node:crypto";
|
|
30248
30452
|
import os8 from "node:os";
|
|
30249
30453
|
import path25 from "node:path";
|
|
30250
30454
|
|
|
@@ -30252,12 +30456,12 @@ import path25 from "node:path";
|
|
|
30252
30456
|
import nodePath from "node:path";
|
|
30253
30457
|
|
|
30254
30458
|
// packages/host-runtime/src/external-thread-repository.ts
|
|
30255
|
-
import { randomUUID as
|
|
30459
|
+
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
30256
30460
|
import os7 from "node:os";
|
|
30257
30461
|
import path22 from "node:path";
|
|
30258
30462
|
|
|
30259
30463
|
// packages/host-runtime/src/external-subagent-threads.ts
|
|
30260
|
-
import { createHash as createHash6, randomUUID as
|
|
30464
|
+
import { createHash as createHash6, randomUUID as randomUUID10 } from "node:crypto";
|
|
30261
30465
|
function childCreateRequest(parent, nativeRef, id2) {
|
|
30262
30466
|
const key = createHash6("sha256").update(JSON.stringify([parent.hostThreadId, parent.harnessId, nativeRef.nativeSessionId, id2])).digest("hex");
|
|
30263
30467
|
return `subagent:${key}`;
|
|
@@ -30332,7 +30536,7 @@ function subagentMaterializer(store, parent, previousParent) {
|
|
|
30332
30536
|
return rebind(existing, parent);
|
|
30333
30537
|
}
|
|
30334
30538
|
const provisional = existing ?? await store.createProvisional({
|
|
30335
|
-
hostThreadId: hostThreadIdSchema.parse(
|
|
30539
|
+
hostThreadId: hostThreadIdSchema.parse(randomUUID10()),
|
|
30336
30540
|
createRequestId,
|
|
30337
30541
|
harnessId: parent.harnessId,
|
|
30338
30542
|
cwd: parent.cwd,
|
|
@@ -30505,7 +30709,7 @@ var ExternalThreadRepository = class {
|
|
|
30505
30709
|
throw new Error("Derived Snapshot identity does not belong to its Native Session");
|
|
30506
30710
|
}
|
|
30507
30711
|
return {
|
|
30508
|
-
hostTurnId: hostTurnIdSchema.parse(
|
|
30712
|
+
hostTurnId: hostTurnIdSchema.parse(randomUUID11()),
|
|
30509
30713
|
nativeTurnRef: turn.nativeTurnRef,
|
|
30510
30714
|
...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
|
|
30511
30715
|
};
|
|
@@ -30628,14 +30832,14 @@ var ExternalThreadRepository = class {
|
|
|
30628
30832
|
const aligned = snapshot2.turns.map((turn) => {
|
|
30629
30833
|
const existing = mappingsByNative.get(nativeTurnKey2(turn.nativeTurnRef));
|
|
30630
30834
|
const mapping = existing ?? {
|
|
30631
|
-
hostTurnId: hostTurnIdSchema.parse(
|
|
30835
|
+
hostTurnId: hostTurnIdSchema.parse(randomUUID11()),
|
|
30632
30836
|
nativeTurnRef: turn.nativeTurnRef,
|
|
30633
30837
|
...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
|
|
30634
30838
|
};
|
|
30635
30839
|
return {
|
|
30636
30840
|
snapshot: turn,
|
|
30637
30841
|
mapping: {
|
|
30638
|
-
|
|
30842
|
+
hostTurnId: mapping.hostTurnId,
|
|
30639
30843
|
nativeTurnRef: turn.nativeTurnRef,
|
|
30640
30844
|
...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
|
|
30641
30845
|
}
|
|
@@ -30655,8 +30859,8 @@ var ExternalThreadRepository = class {
|
|
|
30655
30859
|
};
|
|
30656
30860
|
function createExternalThreadRecordInput(input) {
|
|
30657
30861
|
return {
|
|
30658
|
-
hostThreadId: input.hostThreadId ?? hostThreadIdSchema.parse(
|
|
30659
|
-
createRequestId: input.createRequestId ??
|
|
30862
|
+
hostThreadId: input.hostThreadId ?? hostThreadIdSchema.parse(randomUUID11()),
|
|
30863
|
+
createRequestId: input.createRequestId ?? randomUUID11(),
|
|
30660
30864
|
harnessId: input.harnessId,
|
|
30661
30865
|
cwd: input.cwd,
|
|
30662
30866
|
...input.title ? { title: input.title } : {},
|
|
@@ -30774,6 +30978,15 @@ async function executeExternalThreadFork(input) {
|
|
|
30774
30978
|
boundaryIndex = mappings.length - 1;
|
|
30775
30979
|
}
|
|
30776
30980
|
const boundary = mappings[boundaryIndex];
|
|
30981
|
+
if (boundary && source.steeredTurnIds.has(boundary.hostTurnId)) {
|
|
30982
|
+
return {
|
|
30983
|
+
ok: false,
|
|
30984
|
+
error: {
|
|
30985
|
+
code: -32080,
|
|
30986
|
+
message: "This Turn took steered input; reopen the Thread before forking from it"
|
|
30987
|
+
}
|
|
30988
|
+
};
|
|
30989
|
+
}
|
|
30777
30990
|
if (boundaryIndex < 0 || !boundary?.nativeCheckpointRef) {
|
|
30778
30991
|
return {
|
|
30779
30992
|
ok: false,
|
|
@@ -30830,6 +31043,7 @@ async function executeExternalThreadFork(input) {
|
|
|
30830
31043
|
return { ok: false, error: mapExternalThreadHarnessError(opened.error, "fork") };
|
|
30831
31044
|
}
|
|
30832
31045
|
const session = opened.value;
|
|
31046
|
+
await inheritSourceModel(source, session);
|
|
30833
31047
|
const inheritedPermissionModeId = await inheritSourcePermissionMode(source, session);
|
|
30834
31048
|
try {
|
|
30835
31049
|
const derivedNativeRef = session.initialState.nativeRef;
|
|
@@ -30847,7 +31061,7 @@ async function executeExternalThreadFork(input) {
|
|
|
30847
31061
|
source.harnessId,
|
|
30848
31062
|
provisional.transportModelId
|
|
30849
31063
|
);
|
|
30850
|
-
if (effectiveModel && selection
|
|
31064
|
+
if (effectiveModel && selection && selection.model?.id !== effectiveModel.id) {
|
|
30851
31065
|
const transportModelId = encodeExternalTransportSelection(source.harnessId, {
|
|
30852
31066
|
...selection,
|
|
30853
31067
|
model: effectiveModel
|
|
@@ -30892,6 +31106,22 @@ async function executeExternalThreadFork(input) {
|
|
|
30892
31106
|
};
|
|
30893
31107
|
}
|
|
30894
31108
|
}
|
|
31109
|
+
async function inheritSourceModel(source, session) {
|
|
31110
|
+
let persisted;
|
|
31111
|
+
try {
|
|
31112
|
+
persisted = decodeExternalTransportSelection(source.harnessId, source.transportModelId)?.model;
|
|
31113
|
+
} catch {
|
|
31114
|
+
persisted = void 0;
|
|
31115
|
+
}
|
|
31116
|
+
const sourceModel = source.stateObserver.state.effectiveModel ?? source.requestedModel ?? persisted;
|
|
31117
|
+
if (!sourceModel || !session.capabilities.configuration.selectModel || session.initialState.effectiveModel !== void 0) {
|
|
31118
|
+
return;
|
|
31119
|
+
}
|
|
31120
|
+
try {
|
|
31121
|
+
await session.execute({ type: "model.select", model: sourceModel });
|
|
31122
|
+
} catch {
|
|
31123
|
+
}
|
|
31124
|
+
}
|
|
30895
31125
|
async function inheritSourcePermissionMode(source, session) {
|
|
30896
31126
|
const sourceModeId = source.stateObserver.state.effectivePermissionModeId ?? source.requestedPermissionModeId;
|
|
30897
31127
|
if (!sourceModeId) return void 0;
|
|
@@ -31513,6 +31743,16 @@ async function executeExternalThreadRollback(input) {
|
|
|
31513
31743
|
if (derived.running) {
|
|
31514
31744
|
return { ok: false, error: { code: -32072, message: "External Thread has an active Turn" } };
|
|
31515
31745
|
}
|
|
31746
|
+
const undone = derived.record.turnMappings.slice(-rollback.numTurns);
|
|
31747
|
+
if (undone.some((mapping) => derived.steeredTurnIds.has(mapping.hostTurnId))) {
|
|
31748
|
+
return {
|
|
31749
|
+
ok: false,
|
|
31750
|
+
error: {
|
|
31751
|
+
code: -32080,
|
|
31752
|
+
message: "A Turn here took steered input; reopen the Thread before undoing Turns"
|
|
31753
|
+
}
|
|
31754
|
+
};
|
|
31755
|
+
}
|
|
31516
31756
|
const refreshError = await runtime.refresh(derived);
|
|
31517
31757
|
if (refreshError) return { ok: false, error: refreshError };
|
|
31518
31758
|
if (expectedLastTurnId !== void 0 && derived.record.turnMappings.at(-1)?.hostTurnId !== expectedLastTurnId) {
|
|
@@ -32312,6 +32552,7 @@ var ExternalThreadRuntime = class {
|
|
|
32312
32552
|
#repository;
|
|
32313
32553
|
#lifecycle = new ExternalThreadLifecycle();
|
|
32314
32554
|
#hasRunningDescendants;
|
|
32555
|
+
#steeredTurnIds = /* @__PURE__ */ new Map();
|
|
32315
32556
|
#subagentRunning;
|
|
32316
32557
|
#threads = /* @__PURE__ */ new Map();
|
|
32317
32558
|
constructor(input) {
|
|
@@ -32325,7 +32566,8 @@ var ExternalThreadRuntime = class {
|
|
|
32325
32566
|
this.idleRelease = new ExternalThreadIdleRelease({
|
|
32326
32567
|
threads: () => this.values(),
|
|
32327
32568
|
get: (id2) => this.get(id2),
|
|
32328
|
-
|
|
32569
|
+
// Idle release detaches only the Native Session. Host Thread state survives restoration.
|
|
32570
|
+
remove: (id2) => this.#detach(id2),
|
|
32329
32571
|
queue: input.idleRelease?.queue ?? new DesktopRequestQueue(),
|
|
32330
32572
|
canRelease: (thread) => !thread.sessionUnavailable && !this.#lifecycle.busy(thread.id) && (input.idleRelease?.canRelease(thread) ?? false),
|
|
32331
32573
|
...input.idleRelease?.onClosed ? { onClosed: input.idleRelease.onClosed } : {},
|
|
@@ -32335,14 +32577,21 @@ var ExternalThreadRuntime = class {
|
|
|
32335
32577
|
get(threadId2) {
|
|
32336
32578
|
return this.#threads.get(threadId2);
|
|
32337
32579
|
}
|
|
32580
|
+
#detach(threadId2) {
|
|
32581
|
+
const thread = this.#threads.get(threadId2);
|
|
32582
|
+
this.#threads.delete(threadId2);
|
|
32583
|
+
if (!thread || thread.steeredTurnIds.size === 0) this.#steeredTurnIds.delete(threadId2);
|
|
32584
|
+
}
|
|
32338
32585
|
values() {
|
|
32339
32586
|
return [...this.#threads.values()];
|
|
32340
32587
|
}
|
|
32341
32588
|
remove(threadId2) {
|
|
32342
32589
|
this.#threads.delete(threadId2);
|
|
32590
|
+
this.#steeredTurnIds.delete(threadId2);
|
|
32343
32591
|
}
|
|
32344
32592
|
clear() {
|
|
32345
32593
|
this.#threads.clear();
|
|
32594
|
+
this.#steeredTurnIds.clear();
|
|
32346
32595
|
}
|
|
32347
32596
|
drain() {
|
|
32348
32597
|
return this.#lifecycle.drain();
|
|
@@ -32399,6 +32648,11 @@ var ExternalThreadRuntime = class {
|
|
|
32399
32648
|
...effectivePermissionModeId ? { effectivePermissionModeId } : {}
|
|
32400
32649
|
};
|
|
32401
32650
|
const running = this.#subagentRunning(input.record.hostThreadId);
|
|
32651
|
+
let steeredTurnIds = this.#steeredTurnIds.get(input.record.hostThreadId);
|
|
32652
|
+
if (!steeredTurnIds) {
|
|
32653
|
+
steeredTurnIds = /* @__PURE__ */ new Set();
|
|
32654
|
+
this.#steeredTurnIds.set(input.record.hostThreadId, steeredTurnIds);
|
|
32655
|
+
}
|
|
32402
32656
|
const externalThread = {
|
|
32403
32657
|
id: input.record.hostThreadId,
|
|
32404
32658
|
cwd: input.record.cwd,
|
|
@@ -32423,11 +32677,13 @@ var ExternalThreadRuntime = class {
|
|
|
32423
32677
|
usageTurnId: null,
|
|
32424
32678
|
projectedTurns: /* @__PURE__ */ new Map(),
|
|
32425
32679
|
responseGates: /* @__PURE__ */ new Map(),
|
|
32680
|
+
pendingSteerProjections: /* @__PURE__ */ new Set(),
|
|
32426
32681
|
ephemeralTurnIds: /* @__PURE__ */ new Set(),
|
|
32427
32682
|
persistenceError: null,
|
|
32428
32683
|
projectedTerminalTurnId: null,
|
|
32429
32684
|
ignoredInteractionIds: /* @__PURE__ */ new Set(),
|
|
32430
|
-
sessionUnavailable: false
|
|
32685
|
+
sessionUnavailable: false,
|
|
32686
|
+
steeredTurnIds
|
|
32431
32687
|
};
|
|
32432
32688
|
this.idleRelease.touch(externalThread);
|
|
32433
32689
|
externalThread.outputTask = this.#consumeOutputs(externalThread);
|
|
@@ -32484,13 +32740,13 @@ var ExternalThreadRuntime = class {
|
|
|
32484
32740
|
const retire = async () => {
|
|
32485
32741
|
if (this.#threads.get(parentId) !== parent || this.#threads.get(child.id) !== child) return;
|
|
32486
32742
|
if (bestEffort) {
|
|
32487
|
-
this
|
|
32743
|
+
this.remove(child.id);
|
|
32488
32744
|
await child.session.close();
|
|
32489
32745
|
await child.outputTask;
|
|
32490
32746
|
} else {
|
|
32491
32747
|
child.sessionUnavailable = true;
|
|
32492
32748
|
await this.#lifecycle.release(child.id, child.session, child.outputTask);
|
|
32493
|
-
if (this.#threads.get(child.id) === child) this
|
|
32749
|
+
if (this.#threads.get(child.id) === child) this.remove(child.id);
|
|
32494
32750
|
}
|
|
32495
32751
|
};
|
|
32496
32752
|
if (bestEffort) await retire().catch(this.#diagnose);
|
|
@@ -32863,6 +33119,71 @@ var ExternalThreadRuntime = class {
|
|
|
32863
33119
|
};
|
|
32864
33120
|
|
|
32865
33121
|
// packages/host-runtime/src/external-turn-steering.ts
|
|
33122
|
+
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
33123
|
+
|
|
33124
|
+
// packages/host-runtime/src/external-command-routing.ts
|
|
33125
|
+
var ExternalCommandError = class extends Error {
|
|
33126
|
+
constructor(code, message2) {
|
|
33127
|
+
super(message2);
|
|
33128
|
+
this.code = code;
|
|
33129
|
+
}
|
|
33130
|
+
code;
|
|
33131
|
+
};
|
|
33132
|
+
function isExternalCommandCandidate(text) {
|
|
33133
|
+
return /^\/[^\s/]+(?:\s|$)/u.test(text.trimStart());
|
|
33134
|
+
}
|
|
33135
|
+
async function inspectLiveCommandCatalog(commands, timeoutMs = 1e3) {
|
|
33136
|
+
let timeout;
|
|
33137
|
+
try {
|
|
33138
|
+
const result = await Promise.race([
|
|
33139
|
+
commands.list(),
|
|
33140
|
+
new Promise((resolve) => {
|
|
33141
|
+
timeout = setTimeout(() => resolve(null), timeoutMs);
|
|
33142
|
+
})
|
|
33143
|
+
]);
|
|
33144
|
+
return result?.ok ? harnessCommandCatalogSchema.parse(result.value) : null;
|
|
33145
|
+
} catch {
|
|
33146
|
+
return null;
|
|
33147
|
+
} finally {
|
|
33148
|
+
if (timeout !== void 0) clearTimeout(timeout);
|
|
33149
|
+
}
|
|
33150
|
+
}
|
|
33151
|
+
async function resolveExternalCommand(commands, text, options2 = {}) {
|
|
33152
|
+
const catalog = await commands.list();
|
|
33153
|
+
if (!catalog.ok) throw new ExternalCommandError(-32073, catalog.error.message);
|
|
33154
|
+
const commandText = text.trim();
|
|
33155
|
+
const matched = catalog.value.commands.toSorted((left, right) => right.invocation.length - left.invocation.length).find((command) => {
|
|
33156
|
+
if (commandText === command.invocation) return true;
|
|
33157
|
+
return command.argumentMode === "text" && commandText.startsWith(`${command.invocation} `);
|
|
33158
|
+
});
|
|
33159
|
+
if (!matched) {
|
|
33160
|
+
const name = /^\/(\S+)/u.exec(commandText)?.[1] ?? "";
|
|
33161
|
+
if (name && !isExcludedLiveCommand(name, "command") && options2.liveCatalogPending?.(catalog.value)) {
|
|
33162
|
+
return null;
|
|
33163
|
+
}
|
|
33164
|
+
throw new ExternalCommandError(
|
|
33165
|
+
-32078,
|
|
33166
|
+
"External Harness does not expose the requested command"
|
|
33167
|
+
);
|
|
33168
|
+
}
|
|
33169
|
+
const argumentText = commandText.slice(matched.invocation.length).trimStart();
|
|
33170
|
+
return {
|
|
33171
|
+
descriptor: matched,
|
|
33172
|
+
...argumentText.length > 0 ? { arguments: { text: argumentText } } : {}
|
|
33173
|
+
};
|
|
33174
|
+
}
|
|
33175
|
+
|
|
33176
|
+
// packages/host-runtime/src/external-turn-steering.ts
|
|
33177
|
+
function isHarnessCommand(thread, text) {
|
|
33178
|
+
return thread.session.commands !== void 0 && isExternalCommandCandidate(restoreHarnessCommandMentions(text));
|
|
33179
|
+
}
|
|
33180
|
+
function externalSteeringDelivery(thread, text) {
|
|
33181
|
+
if (text !== void 0 && isHarnessCommand(thread, text)) return "newTurn";
|
|
33182
|
+
if (thread.session.readCapabilities) {
|
|
33183
|
+
return thread.session.readCapabilities().then((capabilities) => capabilities.steer === true ? "activeTurn" : "newTurn");
|
|
33184
|
+
}
|
|
33185
|
+
return thread.session.capabilities.steer === true ? "activeTurn" : "newTurn";
|
|
33186
|
+
}
|
|
32866
33187
|
var ExternalSteerError = class extends Error {
|
|
32867
33188
|
constructor(code, message2) {
|
|
32868
33189
|
super(message2);
|
|
@@ -32870,6 +33191,11 @@ var ExternalSteerError = class extends Error {
|
|
|
32870
33191
|
}
|
|
32871
33192
|
code;
|
|
32872
33193
|
};
|
|
33194
|
+
var ExternalSteerNotTakenError = class extends ExternalSteerError {
|
|
33195
|
+
constructor(message2) {
|
|
33196
|
+
super(-32074, message2);
|
|
33197
|
+
}
|
|
33198
|
+
};
|
|
32873
33199
|
function parseInput(params) {
|
|
32874
33200
|
if (typeof params.expectedTurnId !== "string" || !params.expectedTurnId.trim()) {
|
|
32875
33201
|
throw new ExternalSteerError(-32602, "External steering requires expectedTurnId");
|
|
@@ -32886,12 +33212,47 @@ function parseInput(params) {
|
|
|
32886
33212
|
if (clientUserMessageId != null && (typeof clientUserMessageId !== "string" || !clientUserMessageId.trim())) {
|
|
32887
33213
|
throw new ExternalSteerError(-32602, "External steering message identity is invalid");
|
|
32888
33214
|
}
|
|
33215
|
+
const delivery = params[THREAD_STEER_DELIVERY_PARAM];
|
|
33216
|
+
const parsedDelivery = delivery == null ? void 0 : threadSteerDeliverySchema.safeParse(delivery);
|
|
33217
|
+
if (parsedDelivery && !parsedDelivery.success) {
|
|
33218
|
+
throw new ExternalSteerError(-32602, "External steering delivery is invalid");
|
|
33219
|
+
}
|
|
32889
33220
|
return {
|
|
32890
33221
|
expectedTurnId: params.expectedTurnId,
|
|
32891
33222
|
text,
|
|
32892
|
-
...typeof clientUserMessageId === "string" ? { clientUserMessageId } : {}
|
|
33223
|
+
...typeof clientUserMessageId === "string" ? { clientUserMessageId } : {},
|
|
33224
|
+
...parsedDelivery ? { delivery: parsedDelivery.data } : {}
|
|
32893
33225
|
};
|
|
32894
33226
|
}
|
|
33227
|
+
async function insertNativeSteer(thread, input, host) {
|
|
33228
|
+
const restored = restoreHarnessCommandMentions(input.text);
|
|
33229
|
+
const steered = [{ type: "text", text: rewriteDelegationMentionText(restored) }];
|
|
33230
|
+
const displayed = [{ type: "text", text: restored }];
|
|
33231
|
+
const projectionDone = Promise.withResolvers();
|
|
33232
|
+
thread.pendingSteerProjections.add(projectionDone.promise);
|
|
33233
|
+
try {
|
|
33234
|
+
const result = await thread.session.execute({
|
|
33235
|
+
type: "turn.steer",
|
|
33236
|
+
turnId: input.turnId,
|
|
33237
|
+
input: steered
|
|
33238
|
+
});
|
|
33239
|
+
if (!result.ok) throw new ExternalSteerNotTakenError(result.error.message);
|
|
33240
|
+
thread.steeredTurnIds.add(input.turnId);
|
|
33241
|
+
const item = {
|
|
33242
|
+
type: "userMessage",
|
|
33243
|
+
itemId: hostItemIdSchema.parse(randomUUID12()),
|
|
33244
|
+
input: displayed
|
|
33245
|
+
};
|
|
33246
|
+
try {
|
|
33247
|
+
await host.project(input.turnId, item, input.clientUserMessageId);
|
|
33248
|
+
} catch (error51) {
|
|
33249
|
+
host.diagnose(error51);
|
|
33250
|
+
}
|
|
33251
|
+
} finally {
|
|
33252
|
+
projectionDone.resolve(void 0);
|
|
33253
|
+
thread.pendingSteerProjections.delete(projectionDone.promise);
|
|
33254
|
+
}
|
|
33255
|
+
}
|
|
32895
33256
|
var ExternalTurnSteering = class {
|
|
32896
33257
|
constructor(timeoutMs = 2e4) {
|
|
32897
33258
|
this.timeoutMs = timeoutMs;
|
|
@@ -32903,7 +33264,7 @@ var ExternalTurnSteering = class {
|
|
|
32903
33264
|
hasPending(threadId2) {
|
|
32904
33265
|
return threadId2 === void 0 ? this.#pending.size > 0 : this.#pending.has(threadId2);
|
|
32905
33266
|
}
|
|
32906
|
-
run(thread, params, start) {
|
|
33267
|
+
run(thread, params, start, insert) {
|
|
32907
33268
|
try {
|
|
32908
33269
|
const input = parseInput(params);
|
|
32909
33270
|
if (this.#closed)
|
|
@@ -32925,7 +33286,7 @@ var ExternalTurnSteering = class {
|
|
|
32925
33286
|
if (!thread.running || thread.activeTurnId !== input.expectedTurnId) {
|
|
32926
33287
|
throw new ExternalSteerError(-32074, "External steering must reference the active Turn");
|
|
32927
33288
|
}
|
|
32928
|
-
const result = this.#
|
|
33289
|
+
const result = this.#deliver(thread, input, start, insert);
|
|
32929
33290
|
if (key) {
|
|
32930
33291
|
const receipt2 = { fingerprint, result, settled: false };
|
|
32931
33292
|
this.#receipts.set(key, receipt2);
|
|
@@ -32948,6 +33309,56 @@ var ExternalTurnSteering = class {
|
|
|
32948
33309
|
return Promise.reject(error51);
|
|
32949
33310
|
}
|
|
32950
33311
|
}
|
|
33312
|
+
/**
|
|
33313
|
+
* A Renderer that already presented a delivery gets exactly that one. Otherwise native delivery
|
|
33314
|
+
* is tried only when the Session can take the input now, and input the Harness did not take
|
|
33315
|
+
* falls back to stopping and restarting, so no case is worse than the stop-then-start path.
|
|
33316
|
+
*/
|
|
33317
|
+
#deliver(thread, input, start, insert) {
|
|
33318
|
+
const delivery = input.delivery === "newTurn" || isHarnessCommand(thread, input.text) ? "newTurn" : input.delivery ?? externalSteeringDelivery(thread);
|
|
33319
|
+
const deliver = (mode) => {
|
|
33320
|
+
if (this.#closed || !thread.running || thread.activeTurnId !== input.expectedTurnId) {
|
|
33321
|
+
throw new ExternalSteerError(-32074, "External steering target is no longer active");
|
|
33322
|
+
}
|
|
33323
|
+
if (this.hasPending(thread.id))
|
|
33324
|
+
throw new ExternalSteerError(-32072, "External Thread is already changing direction");
|
|
33325
|
+
if (mode === "newTurn") return this.#replace(thread, input, start);
|
|
33326
|
+
const native = insert({
|
|
33327
|
+
turnId: thread.activeTurnId,
|
|
33328
|
+
text: input.text,
|
|
33329
|
+
...input.clientUserMessageId ? { clientUserMessageId: input.clientUserMessageId } : {}
|
|
33330
|
+
}).then((admitted) => ({ ...admitted, delivery: "activeTurn" }));
|
|
33331
|
+
if (input.delivery === "activeTurn") return native;
|
|
33332
|
+
return native.catch(async (error51) => {
|
|
33333
|
+
if (!(error51 instanceof ExternalSteerNotTakenError)) throw error51;
|
|
33334
|
+
if (thread.running || thread.activeTurnId) return deliver("newTurn");
|
|
33335
|
+
const assertActive = () => {
|
|
33336
|
+
if (this.#closed)
|
|
33337
|
+
throw new ExternalSteerError(-32074, "External steering connection is closed");
|
|
33338
|
+
};
|
|
33339
|
+
return { ...await start(input.text, assertActive), delivery: "newTurn" };
|
|
33340
|
+
});
|
|
33341
|
+
};
|
|
33342
|
+
if (typeof delivery === "string") return deliver(delivery);
|
|
33343
|
+
const failure = Promise.withResolvers();
|
|
33344
|
+
let failureReason = null;
|
|
33345
|
+
const pending = {
|
|
33346
|
+
turnId: input.expectedTurnId,
|
|
33347
|
+
resolve: () => void 0,
|
|
33348
|
+
reject(error51) {
|
|
33349
|
+
failureReason ??= error51;
|
|
33350
|
+
failure.reject(error51);
|
|
33351
|
+
}
|
|
33352
|
+
};
|
|
33353
|
+
this.#pending.set(thread.id, pending);
|
|
33354
|
+
return Promise.race([delivery, failure.promise]).then((mode) => {
|
|
33355
|
+
if (failureReason) throw failureReason;
|
|
33356
|
+
if (this.#pending.get(thread.id) === pending) this.#pending.delete(thread.id);
|
|
33357
|
+
return deliver(mode);
|
|
33358
|
+
}).finally(() => {
|
|
33359
|
+
if (this.#pending.get(thread.id) === pending) this.#pending.delete(thread.id);
|
|
33360
|
+
});
|
|
33361
|
+
}
|
|
32951
33362
|
terminal(threadId2, turnId, outcome) {
|
|
32952
33363
|
const pending = this.#pending.get(threadId2);
|
|
32953
33364
|
if (pending?.turnId === turnId) pending.resolve(outcome);
|
|
@@ -33002,7 +33413,9 @@ var ExternalTurnSteering = class {
|
|
|
33002
33413
|
thread.session.execute({ type: "turn.cancel", turnId }),
|
|
33003
33414
|
failure.promise
|
|
33004
33415
|
]);
|
|
33005
|
-
if (!cancelled.ok
|
|
33416
|
+
if (!cancelled.ok && cancelled.error.code !== "invalidState") {
|
|
33417
|
+
throw new ExternalSteerError(-32074, cancelled.error.message);
|
|
33418
|
+
}
|
|
33006
33419
|
const outcome = await Promise.race([terminal3.promise, failure.promise]);
|
|
33007
33420
|
clearTimeout(timeout);
|
|
33008
33421
|
const assertActive = () => {
|
|
@@ -33020,7 +33433,7 @@ var ExternalTurnSteering = class {
|
|
|
33020
33433
|
if (thread.running || thread.activeTurnId) {
|
|
33021
33434
|
throw new ExternalSteerError(-32072, "Another External Turn started before replacement");
|
|
33022
33435
|
}
|
|
33023
|
-
return await start(input.text, assertActive);
|
|
33436
|
+
return { ...await start(input.text, assertActive), delivery: "newTurn" };
|
|
33024
33437
|
} finally {
|
|
33025
33438
|
clearTimeout(timeout);
|
|
33026
33439
|
if (this.#pending.get(thread.id) === pending) this.#pending.delete(thread.id);
|
|
@@ -33028,58 +33441,6 @@ var ExternalTurnSteering = class {
|
|
|
33028
33441
|
}
|
|
33029
33442
|
};
|
|
33030
33443
|
|
|
33031
|
-
// packages/host-runtime/src/external-command-routing.ts
|
|
33032
|
-
var ExternalCommandError = class extends Error {
|
|
33033
|
-
constructor(code, message2) {
|
|
33034
|
-
super(message2);
|
|
33035
|
-
this.code = code;
|
|
33036
|
-
}
|
|
33037
|
-
code;
|
|
33038
|
-
};
|
|
33039
|
-
function isExternalCommandCandidate(text) {
|
|
33040
|
-
return /^\/[^\s/]+(?:\s|$)/u.test(text.trimStart());
|
|
33041
|
-
}
|
|
33042
|
-
async function inspectLiveCommandCatalog(commands, timeoutMs = 1e3) {
|
|
33043
|
-
let timeout;
|
|
33044
|
-
try {
|
|
33045
|
-
const result = await Promise.race([
|
|
33046
|
-
commands.list(),
|
|
33047
|
-
new Promise((resolve) => {
|
|
33048
|
-
timeout = setTimeout(() => resolve(null), timeoutMs);
|
|
33049
|
-
})
|
|
33050
|
-
]);
|
|
33051
|
-
return result?.ok ? harnessCommandCatalogSchema.parse(result.value) : null;
|
|
33052
|
-
} catch {
|
|
33053
|
-
return null;
|
|
33054
|
-
} finally {
|
|
33055
|
-
if (timeout !== void 0) clearTimeout(timeout);
|
|
33056
|
-
}
|
|
33057
|
-
}
|
|
33058
|
-
async function resolveExternalCommand(commands, text, options2 = {}) {
|
|
33059
|
-
const catalog = await commands.list();
|
|
33060
|
-
if (!catalog.ok) throw new ExternalCommandError(-32073, catalog.error.message);
|
|
33061
|
-
const commandText = text.trim();
|
|
33062
|
-
const matched = catalog.value.commands.toSorted((left, right) => right.invocation.length - left.invocation.length).find((command) => {
|
|
33063
|
-
if (commandText === command.invocation) return true;
|
|
33064
|
-
return command.argumentMode === "text" && commandText.startsWith(`${command.invocation} `);
|
|
33065
|
-
});
|
|
33066
|
-
if (!matched) {
|
|
33067
|
-
const name = /^\/(\S+)/u.exec(commandText)?.[1] ?? "";
|
|
33068
|
-
if (name && !isExcludedLiveCommand(name, "command") && options2.liveCatalogPending?.(catalog.value)) {
|
|
33069
|
-
return null;
|
|
33070
|
-
}
|
|
33071
|
-
throw new ExternalCommandError(
|
|
33072
|
-
-32078,
|
|
33073
|
-
"External Harness does not expose the requested command"
|
|
33074
|
-
);
|
|
33075
|
-
}
|
|
33076
|
-
const argumentText = commandText.slice(matched.invocation.length).trimStart();
|
|
33077
|
-
return {
|
|
33078
|
-
descriptor: matched,
|
|
33079
|
-
...argumentText.length > 0 ? { arguments: { text: argumentText } } : {}
|
|
33080
|
-
};
|
|
33081
|
-
}
|
|
33082
|
-
|
|
33083
33444
|
// packages/host-runtime/src/live-command-catalog-cache.ts
|
|
33084
33445
|
import path23 from "node:path";
|
|
33085
33446
|
var MAX_ENTRIES = 64;
|
|
@@ -33111,7 +33472,7 @@ function sameWorkspace(left, right) {
|
|
|
33111
33472
|
}
|
|
33112
33473
|
|
|
33113
33474
|
// packages/host-runtime/src/harness-delegation-coordinator.ts
|
|
33114
|
-
import { createHash as createHash8, randomUUID as
|
|
33475
|
+
import { createHash as createHash8, randomUUID as randomUUID13 } from "node:crypto";
|
|
33115
33476
|
import path24 from "node:path";
|
|
33116
33477
|
|
|
33117
33478
|
// packages/host-runtime/src/delegation-snapshot.ts
|
|
@@ -33257,6 +33618,15 @@ function projectDelegationThreadSnapshot(input) {
|
|
|
33257
33618
|
// packages/host-runtime/src/harness-delegation-coordinator.ts
|
|
33258
33619
|
var IMPLICIT_DEDUPLICATION_MS = 3e4;
|
|
33259
33620
|
var NATIVE_REF_TIMEOUT_MS = 1e4;
|
|
33621
|
+
function truncateTitle(value2, length) {
|
|
33622
|
+
return value2.slice(0, length).replace(/[\uD800-\uDBFF]$/u, "");
|
|
33623
|
+
}
|
|
33624
|
+
function delegationTitle(parentTitle, input) {
|
|
33625
|
+
const taskName = (input.taskName ?? input.task.trim().split(/\r?\n/u)[0] ?? input.task).replace(/\s+/gu, " ").trim();
|
|
33626
|
+
const subtask = truncateTitle(taskName, 120);
|
|
33627
|
+
const parent = (parentTitle?.trim() || "Untitled Thread").replace(/\s+/gu, " ");
|
|
33628
|
+
return `${subtask} · ${truncateTitle(parent, 200 - subtask.length - 3)}`;
|
|
33629
|
+
}
|
|
33260
33630
|
function delay3(milliseconds) {
|
|
33261
33631
|
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
33262
33632
|
}
|
|
@@ -33283,6 +33653,12 @@ function statusFromThread(thread, busy) {
|
|
|
33283
33653
|
function validateStart(input) {
|
|
33284
33654
|
if (typeof input.task !== "string" || !input.task.trim())
|
|
33285
33655
|
throw new DelegationControlError("INVALID_ARGUMENT", "Task must not be empty");
|
|
33656
|
+
if (input.taskName !== void 0 && (typeof input.taskName !== "string" || !input.taskName.trim() || input.taskName.length > 120)) {
|
|
33657
|
+
throw new DelegationControlError(
|
|
33658
|
+
"INVALID_ARGUMENT",
|
|
33659
|
+
"Task name must contain 1 to 120 characters"
|
|
33660
|
+
);
|
|
33661
|
+
}
|
|
33286
33662
|
if (input.cwd !== void 0 && (typeof input.cwd !== "string" || !input.cwd.trim()))
|
|
33287
33663
|
throw new DelegationControlError("INVALID_ARGUMENT", "cwd must not be empty");
|
|
33288
33664
|
if (input.requestId !== void 0 && (typeof input.requestId !== "string" || !input.requestId.trim())) {
|
|
@@ -33303,7 +33679,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
33303
33679
|
#cancelOfficial;
|
|
33304
33680
|
#startOfficial;
|
|
33305
33681
|
#listOfficial;
|
|
33306
|
-
#
|
|
33682
|
+
#officialThreadMetadata;
|
|
33307
33683
|
#activeOfficialParents;
|
|
33308
33684
|
#externalThreadBusy;
|
|
33309
33685
|
constructor(input) {
|
|
@@ -33320,7 +33696,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
33320
33696
|
this.#cancelOfficial = input.cancelOfficial;
|
|
33321
33697
|
this.#startOfficial = input.startOfficial;
|
|
33322
33698
|
this.#listOfficial = input.listOfficial;
|
|
33323
|
-
this.#
|
|
33699
|
+
this.#officialThreadMetadata = input.officialThreadMetadata;
|
|
33324
33700
|
this.#activeOfficialParents = input.activeOfficialParents;
|
|
33325
33701
|
this.#externalThreadBusy = input.externalThreadBusy;
|
|
33326
33702
|
}
|
|
@@ -33350,8 +33726,14 @@ var HarnessDelegationCoordinator = class {
|
|
|
33350
33726
|
const parentThreadId = await this.#resolveParent(input.parentThreadId);
|
|
33351
33727
|
const parent = await this.#parentMetadata(parentThreadId);
|
|
33352
33728
|
const selectedCwd = input.cwd ?? parent.cwd ?? process.cwd();
|
|
33729
|
+
const title = delegationTitle(parent.title, input);
|
|
33353
33730
|
if (input.harnessId === "codex") {
|
|
33354
|
-
const result = await this.#startOfficial({
|
|
33731
|
+
const result = await this.#startOfficial({
|
|
33732
|
+
...input,
|
|
33733
|
+
parentThreadId,
|
|
33734
|
+
cwd: selectedCwd,
|
|
33735
|
+
title
|
|
33736
|
+
});
|
|
33355
33737
|
return { ...result, parentThreadId, cwd: result.cwd ?? selectedCwd };
|
|
33356
33738
|
}
|
|
33357
33739
|
const startInput = { ...input, parentThreadId, cwd: path24.resolve(selectedCwd) };
|
|
@@ -33394,17 +33776,17 @@ var HarnessDelegationCoordinator = class {
|
|
|
33394
33776
|
});
|
|
33395
33777
|
this.#validateConfiguration(inspected.inspection, input.model, input.thinkingOptionId);
|
|
33396
33778
|
}
|
|
33397
|
-
const delegationId = hostThreadIdSchema.parse(
|
|
33398
|
-
const childThreadId = hostThreadIdSchema.parse(
|
|
33399
|
-
const turnId = hostTurnIdSchema.parse(
|
|
33400
|
-
const createRequestId = input.requestId ? `delegation:${input.requestId}` :
|
|
33779
|
+
const delegationId = hostThreadIdSchema.parse(randomUUID13());
|
|
33780
|
+
const childThreadId = hostThreadIdSchema.parse(randomUUID13());
|
|
33781
|
+
const turnId = hostTurnIdSchema.parse(randomUUID13());
|
|
33782
|
+
const createRequestId = input.requestId ? `delegation:${input.requestId}` : randomUUID13();
|
|
33401
33783
|
let record4 = await this.#repository.createProvisional(
|
|
33402
33784
|
createExternalThreadRecordInput({
|
|
33403
33785
|
hostThreadId: childThreadId,
|
|
33404
33786
|
createRequestId,
|
|
33405
33787
|
harnessId: harnessIdSchema.parse(targetHarnessId),
|
|
33406
33788
|
cwd: startInput.cwd,
|
|
33407
|
-
title
|
|
33789
|
+
title,
|
|
33408
33790
|
transportModelId: input.model || input.thinkingOptionId ? encodeExternalTransportSelection(targetHarnessId, {
|
|
33409
33791
|
...input.model ? { model: input.model } : {},
|
|
33410
33792
|
...input.thinkingOptionId ? { thinkingOptionId: input.thinkingOptionId } : {}
|
|
@@ -33551,7 +33933,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
33551
33933
|
if (this.#externalThreadBusy(thread) || thread.activeTurnId) {
|
|
33552
33934
|
throw new DelegationControlError("THREAD_BUSY", "Thread already has an active Turn");
|
|
33553
33935
|
}
|
|
33554
|
-
const turnId = hostTurnIdSchema.parse(
|
|
33936
|
+
const turnId = hostTurnIdSchema.parse(randomUUID13());
|
|
33555
33937
|
try {
|
|
33556
33938
|
await this.#startExternalTurn(thread, input.message, turnId);
|
|
33557
33939
|
} catch (error51) {
|
|
@@ -33765,9 +34147,14 @@ var HarnessDelegationCoordinator = class {
|
|
|
33765
34147
|
}
|
|
33766
34148
|
async #parentMetadata(parentThreadId) {
|
|
33767
34149
|
const record4 = await this.#repository.find(parentThreadId);
|
|
33768
|
-
if (record4)
|
|
33769
|
-
|
|
33770
|
-
|
|
34150
|
+
if (record4)
|
|
34151
|
+
return {
|
|
34152
|
+
harnessId: record4.harnessId,
|
|
34153
|
+
cwd: record4.cwd,
|
|
34154
|
+
title: record4.title
|
|
34155
|
+
};
|
|
34156
|
+
const metadata = await this.#officialThreadMetadata(parentThreadId).catch(() => ({}));
|
|
34157
|
+
return { harnessId: "codex", ...metadata };
|
|
33771
34158
|
}
|
|
33772
34159
|
async #existingResult(delegation) {
|
|
33773
34160
|
const record4 = await this.#repository.find(delegation.childHostThreadId);
|
|
@@ -35789,7 +36176,9 @@ function hasValidSessionUsage(value2) {
|
|
|
35789
36176
|
}
|
|
35790
36177
|
function isAdapter(value2) {
|
|
35791
36178
|
if (!value2 || typeof value2 !== "object") return false;
|
|
35792
|
-
return hasValidSessionUsage(value2) && ["inspect", "open", "close"].every((key) => typeof Reflect.get(value2, key) === "function")
|
|
36179
|
+
return hasValidSessionUsage(value2) && ["inspect", "open", "close"].every((key) => typeof Reflect.get(value2, key) === "function") && ["credits", "refreshCredits"].every(
|
|
36180
|
+
(key) => Reflect.get(value2, key) === void 0 || typeof Reflect.get(value2, key) === "function"
|
|
36181
|
+
);
|
|
35793
36182
|
}
|
|
35794
36183
|
function isUsageAdapter(value2) {
|
|
35795
36184
|
if (!value2 || typeof value2 !== "object" || typeof Reflect.get(value2, "close") !== "function")
|
|
@@ -36194,10 +36583,10 @@ var SingleNativeCodexAccount = class {
|
|
|
36194
36583
|
};
|
|
36195
36584
|
|
|
36196
36585
|
// packages/host-runtime/src/codex-runtime/official-runtime-owner.ts
|
|
36197
|
-
import { randomUUID as
|
|
36586
|
+
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
36198
36587
|
|
|
36199
36588
|
// packages/host-runtime/src/official-request-broker.ts
|
|
36200
|
-
import { randomUUID as
|
|
36589
|
+
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
36201
36590
|
var INTERNAL_REQUEST_PREFIX = "codexhost:official:";
|
|
36202
36591
|
var MAX_RETIRED_IDS = 1024;
|
|
36203
36592
|
function isRecord15(value2) {
|
|
@@ -36213,7 +36602,7 @@ var OfficialRequestBroker = class {
|
|
|
36213
36602
|
constructor(input) {
|
|
36214
36603
|
this.#send = input.send;
|
|
36215
36604
|
this.#timeoutMs = input.timeoutMs ?? 3e4;
|
|
36216
|
-
this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${
|
|
36605
|
+
this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${randomUUID14()}`);
|
|
36217
36606
|
}
|
|
36218
36607
|
get pendingCount() {
|
|
36219
36608
|
return this.#pending.size;
|
|
@@ -36567,7 +36956,7 @@ var OfficialRuntimeOwner = class {
|
|
|
36567
36956
|
}
|
|
36568
36957
|
#attach(role, output, onBackendStopped) {
|
|
36569
36958
|
const client = {
|
|
36570
|
-
id:
|
|
36959
|
+
id: randomUUID15(),
|
|
36571
36960
|
role,
|
|
36572
36961
|
output,
|
|
36573
36962
|
...onBackendStopped ? { onBackendStopped } : {},
|
|
@@ -36725,7 +37114,7 @@ var OfficialRuntimeOwner = class {
|
|
|
36725
37114
|
if (!object4(value2)) return client.output(event);
|
|
36726
37115
|
if (typeof value2.id === "string" || typeof value2.id === "number") {
|
|
36727
37116
|
if (typeof value2.method === "string") {
|
|
36728
|
-
const id2 = `codexhost:server:${client.id}:${event.generation}:${
|
|
37117
|
+
const id2 = `codexhost:server:${client.id}:${event.generation}:${randomUUID15()}`;
|
|
36729
37118
|
client.serverRequests.set(id2, value2.id);
|
|
36730
37119
|
const projected = { ...value2, id: id2 };
|
|
36731
37120
|
return client.output({
|
|
@@ -36901,16 +37290,16 @@ var OfficialRuntimeScope = class {
|
|
|
36901
37290
|
#scheduleRecovery() {
|
|
36902
37291
|
if (!this.#recovery || this.#closed || this.#recoveryTimer || this.#starting) return;
|
|
36903
37292
|
const { delaysMs } = this.#recovery;
|
|
36904
|
-
const
|
|
37293
|
+
const delay7 = delaysMs[Math.min(this.#recoveryAttempt, delaysMs.length - 1)] ?? 0;
|
|
36905
37294
|
this.#recoveryAttempt++;
|
|
36906
37295
|
this.#diagnosticOutput.write(
|
|
36907
|
-
`codexhost: official Codex is unavailable; restarting in ${String(
|
|
37296
|
+
`codexhost: official Codex is unavailable; restarting in ${String(delay7)}ms
|
|
36908
37297
|
`
|
|
36909
37298
|
);
|
|
36910
37299
|
const timer = setTimeout(() => {
|
|
36911
37300
|
this.#recoveryTimer = void 0;
|
|
36912
37301
|
this.start().catch(() => void 0);
|
|
36913
|
-
},
|
|
37302
|
+
}, delay7);
|
|
36914
37303
|
timer.unref();
|
|
36915
37304
|
this.#recoveryTimer = timer;
|
|
36916
37305
|
}
|
|
@@ -37657,6 +38046,16 @@ async function moveThreadSection(input) {
|
|
|
37657
38046
|
}
|
|
37658
38047
|
}
|
|
37659
38048
|
|
|
38049
|
+
// packages/host-runtime/src/external-thread-official-defaults.ts
|
|
38050
|
+
var EMPTY_RESULTS = /* @__PURE__ */ new Map([
|
|
38051
|
+
["thread/attachment/list", () => ({ data: [], nextCursor: null })],
|
|
38052
|
+
["thread/queue/list", () => ({ data: [], nextCursor: null })],
|
|
38053
|
+
["thread/settings/update", () => ({})]
|
|
38054
|
+
]);
|
|
38055
|
+
function externalThreadEmptyOfficialResult(method) {
|
|
38056
|
+
return EMPTY_RESULTS.get(method)?.();
|
|
38057
|
+
}
|
|
38058
|
+
|
|
37660
38059
|
// packages/host-runtime/src/observed-session-usage.ts
|
|
37661
38060
|
var ObservedSessionUsage = class {
|
|
37662
38061
|
constructor(providers, prices, diagnose) {
|
|
@@ -37825,16 +38224,6 @@ function officialThreadBusy(thread) {
|
|
|
37825
38224
|
const latestTurn = turns.at(-1);
|
|
37826
38225
|
return isRecord18(latestTurn) && (latestTurn.status === "inProgress" || latestTurn.status === "running");
|
|
37827
38226
|
}
|
|
37828
|
-
function isCreditsAdapter(adapter) {
|
|
37829
|
-
return typeof adapter.credits === "function";
|
|
37830
|
-
}
|
|
37831
|
-
function projectAccountCredits(value2) {
|
|
37832
|
-
if (!isRecord18(value2)) return null;
|
|
37833
|
-
const rest = { ...value2 };
|
|
37834
|
-
delete rest.fetchedAt;
|
|
37835
|
-
const parsed2 = accountCreditsSnapshotSchema.safeParse(rest);
|
|
37836
|
-
return parsed2.success ? parsed2.data : null;
|
|
37837
|
-
}
|
|
37838
38227
|
function errorMessage4(error51) {
|
|
37839
38228
|
return error51 instanceof Error ? error51.message : String(error51);
|
|
37840
38229
|
}
|
|
@@ -38005,6 +38394,7 @@ var AppServerHost = class {
|
|
|
38005
38394
|
#plugins;
|
|
38006
38395
|
#launchSettings;
|
|
38007
38396
|
#accountInspections = new HarnessAccountInspectionCache();
|
|
38397
|
+
#installationTasks = new HarnessInstallationTasks();
|
|
38008
38398
|
#externalRuntime;
|
|
38009
38399
|
#executionHosts = /* @__PURE__ */ new WeakMap();
|
|
38010
38400
|
#externalPrewarms = new ExternalThreadPrewarms();
|
|
@@ -38035,7 +38425,7 @@ var AppServerHost = class {
|
|
|
38035
38425
|
#sectionMoves = Promise.resolve();
|
|
38036
38426
|
#writer;
|
|
38037
38427
|
/** Console requests share Desktop handling; their replies return to the console. */
|
|
38038
|
-
#consoleRequestPrefix = `codexhost-console:${
|
|
38428
|
+
#consoleRequestPrefix = `codexhost-console:${randomUUID16()}:`;
|
|
38039
38429
|
#consoleReplies = /* @__PURE__ */ new Map();
|
|
38040
38430
|
#nextConsoleRequest = 0;
|
|
38041
38431
|
#subagentThreadStatuses = /* @__PURE__ */ new Map();
|
|
@@ -38173,7 +38563,7 @@ var AppServerHost = class {
|
|
|
38173
38563
|
cancelOfficial: (input) => this.#cancelOfficialDelegationThread(input),
|
|
38174
38564
|
startOfficial: (input) => this.#startOfficialDelegation(input),
|
|
38175
38565
|
listOfficial: (input) => this.#listDelegationThreads(input),
|
|
38176
|
-
|
|
38566
|
+
officialThreadMetadata: (threadId2) => this.#readOfficialThreadMetadata(threadId2),
|
|
38177
38567
|
activeOfficialParents: () => [...this.#activeOfficialTurns.keys()],
|
|
38178
38568
|
externalThreadBusy: (thread) => this.#externalThreadBusy(thread)
|
|
38179
38569
|
});
|
|
@@ -38819,11 +39209,11 @@ var AppServerHost = class {
|
|
|
38819
39209
|
this.#dispatchDesktopReply(request, () => this.#inspectHarness(request));
|
|
38820
39210
|
return;
|
|
38821
39211
|
}
|
|
38822
|
-
if (request.method === HARNESS_INSTALLATION_METHOD) {
|
|
39212
|
+
if (request.method === HARNESS_INSTALLATION_METHOD || request.method === HARNESS_INSTALLATION_START_METHOD || request.method === HARNESS_INSTALLATION_STATUS_METHOD) {
|
|
38823
39213
|
this.#dispatchDesktopReply(request, async () => {
|
|
38824
|
-
await this.#waitForPlugins();
|
|
38825
39214
|
try {
|
|
38826
|
-
|
|
39215
|
+
if (request.method !== HARNESS_INSTALLATION_STATUS_METHOD) await this.#waitForPlugins();
|
|
39216
|
+
const result = request.method === HARNESS_INSTALLATION_START_METHOD ? this.#installationTasks.start(request.params, this.#externalAdapters) : request.method === HARNESS_INSTALLATION_STATUS_METHOD ? this.#installationTasks.status(request.params) : await handleHarnessInstallation(request.params, this.#externalAdapters);
|
|
38827
39217
|
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
|
|
38828
39218
|
} catch (error51) {
|
|
38829
39219
|
await this.#writer.json(
|
|
@@ -38908,6 +39298,10 @@ var AppServerHost = class {
|
|
|
38908
39298
|
await this.#listThreadOwnership(request);
|
|
38909
39299
|
return;
|
|
38910
39300
|
}
|
|
39301
|
+
if (request.method === "codexhost/thread/steering/inspect") {
|
|
39302
|
+
await this.#inspectThreadSteering(request);
|
|
39303
|
+
return;
|
|
39304
|
+
}
|
|
38911
39305
|
if (request.method === "codexhost/thread/model/select") {
|
|
38912
39306
|
await this.#selectThreadModel(request);
|
|
38913
39307
|
return;
|
|
@@ -39271,8 +39665,9 @@ var AppServerHost = class {
|
|
|
39271
39665
|
const location = await this.#locateExternalThread(request.params.threadId);
|
|
39272
39666
|
if (await this.#writeResolutionError(request, location)) return;
|
|
39273
39667
|
if (location.kind === "external") {
|
|
39668
|
+
const emptyResult = externalThreadEmptyOfficialResult(request.method);
|
|
39274
39669
|
await this.#writer.json(
|
|
39275
|
-
rpcError(request, -32076, `External Thread does not support ${request.method}`)
|
|
39670
|
+
emptyResult ? rpcEnvelope(request, { result: emptyResult }) : rpcError(request, -32076, `External Thread does not support ${request.method}`)
|
|
39276
39671
|
);
|
|
39277
39672
|
return;
|
|
39278
39673
|
}
|
|
@@ -39484,12 +39879,17 @@ var AppServerHost = class {
|
|
|
39484
39879
|
]);
|
|
39485
39880
|
return thread !== null || childDelegation !== null || delegation !== null;
|
|
39486
39881
|
}
|
|
39487
|
-
async #
|
|
39488
|
-
const response = await this.#requestOfficial("thread/read", { threadId: threadId2 });
|
|
39489
|
-
if (isRecord18(response.error)) return
|
|
39882
|
+
async #readOfficialThreadMetadata(threadId2) {
|
|
39883
|
+
const response = await this.#requestOfficial("thread/read", { threadId: threadId2, includeTurns: false });
|
|
39884
|
+
if (isRecord18(response.error)) return {};
|
|
39490
39885
|
const result = isRecord18(response.result) ? response.result : null;
|
|
39491
39886
|
const thread = result && isRecord18(result.thread) ? result.thread : null;
|
|
39492
|
-
|
|
39887
|
+
if (!thread) return {};
|
|
39888
|
+
const title = typeof thread.name === "string" && thread.name.trim() ? thread.name : thread.preview;
|
|
39889
|
+
return {
|
|
39890
|
+
...typeof thread.cwd === "string" && thread.cwd.trim() ? { cwd: thread.cwd } : {},
|
|
39891
|
+
...typeof title === "string" && title.trim() ? { title } : {}
|
|
39892
|
+
};
|
|
39493
39893
|
}
|
|
39494
39894
|
async #inspectOfficialDelegationTarget(input) {
|
|
39495
39895
|
const response = await this.#requestOfficial("model/list", {});
|
|
@@ -39642,6 +40042,9 @@ var AppServerHost = class {
|
|
|
39642
40042
|
this.#pendingOfficialDelegationThreads.add(threadId2);
|
|
39643
40043
|
let turnId;
|
|
39644
40044
|
try {
|
|
40045
|
+
await this.#requestOfficial("thread/name/set", { threadId: threadId2, name: input.title }).catch(
|
|
40046
|
+
() => void 0
|
|
40047
|
+
);
|
|
39645
40048
|
const turn = await this.#requestOfficial("turn/start", {
|
|
39646
40049
|
threadId: threadId2,
|
|
39647
40050
|
input: [{ type: "text", text: input.task }],
|
|
@@ -39660,7 +40063,7 @@ var AppServerHost = class {
|
|
|
39660
40063
|
throw error51;
|
|
39661
40064
|
}
|
|
39662
40065
|
this.#activeOfficialTurns.set(threadId2, turnId);
|
|
39663
|
-
const delegationId = hostThreadIdSchema.parse(
|
|
40066
|
+
const delegationId = hostThreadIdSchema.parse(randomUUID16());
|
|
39664
40067
|
try {
|
|
39665
40068
|
const source = await this.#repository.find(input.parentThreadId);
|
|
39666
40069
|
const pendingTerminal = this.#pendingOfficialTerminalStatuses.get(threadId2);
|
|
@@ -39848,7 +40251,7 @@ var AppServerHost = class {
|
|
|
39848
40251
|
async #listDelegationThreads(input) {
|
|
39849
40252
|
const [sortKey, sortDirection2] = input.sort.split("-");
|
|
39850
40253
|
const request = {
|
|
39851
|
-
id: `codexhost:delegation-list:${
|
|
40254
|
+
id: `codexhost:delegation-list:${randomUUID16()}`,
|
|
39852
40255
|
method: "thread/list",
|
|
39853
40256
|
params: {
|
|
39854
40257
|
cwd: input.cwd ? [input.cwd] : null,
|
|
@@ -40197,7 +40600,8 @@ var AppServerHost = class {
|
|
|
40197
40600
|
try {
|
|
40198
40601
|
inspection = await adapter.inspect({
|
|
40199
40602
|
...params.data.cwd ? { cwd: params.data.cwd } : {},
|
|
40200
|
-
...params.data.refresh !== void 0 ? { refresh: params.data.refresh } : {}
|
|
40603
|
+
...params.data.refresh !== void 0 ? { refresh: params.data.refresh } : {},
|
|
40604
|
+
...params.data.purpose ? { purpose: params.data.purpose } : {}
|
|
40201
40605
|
});
|
|
40202
40606
|
} catch (error51) {
|
|
40203
40607
|
await this.#writer.json(
|
|
@@ -40328,6 +40732,7 @@ var AppServerHost = class {
|
|
|
40328
40732
|
const result2 = threadUsageInspectionSchema.parse({
|
|
40329
40733
|
threadId: params.data.threadId,
|
|
40330
40734
|
usage: await this.#observedSessionUsage.read(params.data.threadId),
|
|
40735
|
+
accountCreditsSupported: true,
|
|
40331
40736
|
...accountCredits ? { accountCredits } : {}
|
|
40332
40737
|
});
|
|
40333
40738
|
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result2) }));
|
|
@@ -40335,11 +40740,17 @@ var AppServerHost = class {
|
|
|
40335
40740
|
}
|
|
40336
40741
|
if (params.data.refresh === "exact") void resolution.thread.session.refreshUsage?.();
|
|
40337
40742
|
const adapter = this.#externalAdapters.get(resolution.thread.harnessId);
|
|
40338
|
-
if (adapter &&
|
|
40339
|
-
|
|
40743
|
+
if (adapter?.credits && adapter.refreshCredits)
|
|
40744
|
+
void Promise.resolve().then(() => adapter.refreshCredits?.()).catch(() => void 0);
|
|
40745
|
+
let credits = null;
|
|
40746
|
+
try {
|
|
40747
|
+
credits = parseHarnessAccountCredits(adapter?.credits?.());
|
|
40748
|
+
} catch {
|
|
40749
|
+
}
|
|
40340
40750
|
const result = threadUsageInspectionSchema.parse({
|
|
40341
40751
|
threadId: params.data.threadId,
|
|
40342
40752
|
usage: await this.#threadUsage(resolution.thread),
|
|
40753
|
+
accountCreditsSupported: typeof adapter?.credits === "function",
|
|
40343
40754
|
...credits ? { accountCredits: credits } : {}
|
|
40344
40755
|
});
|
|
40345
40756
|
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
|
|
@@ -40383,6 +40794,28 @@ var AppServerHost = class {
|
|
|
40383
40794
|
);
|
|
40384
40795
|
}
|
|
40385
40796
|
}
|
|
40797
|
+
/** Read the same delivery decision that Desktop `turn/steer` will follow. */
|
|
40798
|
+
async #inspectThreadSteering(request) {
|
|
40799
|
+
const params = threadSteeringInspectParamsSchema.safeParse(request.params);
|
|
40800
|
+
if (!params.success) {
|
|
40801
|
+
await this.#writer.json(rpcError(request, -32602, "Invalid Thread steering params"));
|
|
40802
|
+
return;
|
|
40803
|
+
}
|
|
40804
|
+
let delivery;
|
|
40805
|
+
try {
|
|
40806
|
+
const location = await this.#locateExternalThread(params.data.threadId);
|
|
40807
|
+
if (await this.#writeResolutionError(request, location)) return;
|
|
40808
|
+
const thread = location.kind === "external" ? this.#externalRuntime.get(params.data.threadId) : void 0;
|
|
40809
|
+
delivery = location.kind !== "external" ? "official" : thread ? await externalSteeringDelivery(thread, params.data.text) : "newTurn";
|
|
40810
|
+
} catch {
|
|
40811
|
+
await this.#writer.json(
|
|
40812
|
+
rpcError(request, -32081, "Thread steering metadata could not be read")
|
|
40813
|
+
);
|
|
40814
|
+
return;
|
|
40815
|
+
}
|
|
40816
|
+
const result = threadSteeringInspectResultSchema.parse({ delivery });
|
|
40817
|
+
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
|
|
40818
|
+
}
|
|
40386
40819
|
async #inspectThreadCommands(request) {
|
|
40387
40820
|
const params = threadCommandsInspectParamsSchema.safeParse(request.params);
|
|
40388
40821
|
if (!params.success) {
|
|
@@ -40546,7 +40979,7 @@ var AppServerHost = class {
|
|
|
40546
40979
|
if (thread.running || thread.activeTurnId) {
|
|
40547
40980
|
throw new ExternalCommandError(-32072, "External Thread already has an active operation");
|
|
40548
40981
|
}
|
|
40549
|
-
const turnId = requestedTurnId ?? hostTurnIdSchema.parse(
|
|
40982
|
+
const turnId = requestedTurnId ?? hostTurnIdSchema.parse(randomUUID16());
|
|
40550
40983
|
const projection = {
|
|
40551
40984
|
projector: new CodexTurnProjector({
|
|
40552
40985
|
threadId: thread.id,
|
|
@@ -40634,6 +41067,26 @@ var AppServerHost = class {
|
|
|
40634
41067
|
if (!projected.effectiveModel) {
|
|
40635
41068
|
throw new Error("Harness Session did not report an effective Model");
|
|
40636
41069
|
}
|
|
41070
|
+
const transportModelId = encodeExternalTransportSelection(thread.harnessId, {
|
|
41071
|
+
...decodeExternalTransportSelection(thread.harnessId, thread.transportModelId) ?? {},
|
|
41072
|
+
model: projected.effectiveModel
|
|
41073
|
+
});
|
|
41074
|
+
thread.transportModelId = transportModelId;
|
|
41075
|
+
thread.requestedModel = projected.effectiveModel;
|
|
41076
|
+
try {
|
|
41077
|
+
thread.record = await this.#repository.setTransportModelId(
|
|
41078
|
+
thread.record.hostThreadId,
|
|
41079
|
+
transportModelId
|
|
41080
|
+
);
|
|
41081
|
+
} catch (error51) {
|
|
41082
|
+
this.#diagnose(error51);
|
|
41083
|
+
}
|
|
41084
|
+
thread.thread = externalThreadValue({
|
|
41085
|
+
record: { ...thread.record, transportModelId },
|
|
41086
|
+
turns: thread.turns,
|
|
41087
|
+
sessionId: thread.sessionId,
|
|
41088
|
+
running: thread.running
|
|
41089
|
+
});
|
|
40637
41090
|
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(projected) }));
|
|
40638
41091
|
} catch (error51) {
|
|
40639
41092
|
await this.#writer.json(
|
|
@@ -40963,9 +41416,20 @@ var AppServerHost = class {
|
|
|
40963
41416
|
await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
|
|
40964
41417
|
return true;
|
|
40965
41418
|
}
|
|
41419
|
+
/** Refresh history before Desktop acts on native Turn boundaries. */
|
|
40966
41420
|
#refreshExternalThread(thread) {
|
|
40967
41421
|
return this.#externalRuntime.refresh(thread);
|
|
40968
41422
|
}
|
|
41423
|
+
#markExternalHistoryRead(thread, turns) {
|
|
41424
|
+
if (!thread.historyHydrated) return;
|
|
41425
|
+
for (const turnId of thread.steeredTurnIds) {
|
|
41426
|
+
if (turnId !== thread.activeTurnId && turns.some(
|
|
41427
|
+
(turn) => turn.id === turnId && (turn.status === "completed" || turn.status === "failed" || turn.status === "interrupted")
|
|
41428
|
+
)) {
|
|
41429
|
+
thread.steeredTurnIds.delete(turnId);
|
|
41430
|
+
}
|
|
41431
|
+
}
|
|
41432
|
+
}
|
|
40969
41433
|
#persistTerminalIdentity(thread, event) {
|
|
40970
41434
|
return this.#externalRuntime.persistTerminalIdentity(thread, event);
|
|
40971
41435
|
}
|
|
@@ -41167,17 +41631,19 @@ var AppServerHost = class {
|
|
|
41167
41631
|
return;
|
|
41168
41632
|
}
|
|
41169
41633
|
}
|
|
41634
|
+
const readTurns = includeTurns ? [...this.#externalHistoryTurns(thread)] : [];
|
|
41170
41635
|
await this.#writer.json(
|
|
41171
41636
|
rpcEnvelope(request, {
|
|
41172
41637
|
result: {
|
|
41173
41638
|
thread: {
|
|
41174
41639
|
...thread.thread,
|
|
41175
41640
|
...await this.#externalSectionFields(thread.record.hostThreadId),
|
|
41176
|
-
turns:
|
|
41641
|
+
turns: readTurns
|
|
41177
41642
|
}
|
|
41178
41643
|
}
|
|
41179
41644
|
})
|
|
41180
41645
|
);
|
|
41646
|
+
if (includeTurns) this.#markExternalHistoryRead(thread, readTurns);
|
|
41181
41647
|
await this.#replayExternalUsage(thread);
|
|
41182
41648
|
}
|
|
41183
41649
|
async #listExternalHistory(request, thread, params, historyFresh) {
|
|
@@ -41194,6 +41660,9 @@ var AppServerHost = class {
|
|
|
41194
41660
|
const turns = this.#externalHistoryTurns(thread);
|
|
41195
41661
|
const result = request.method === "thread/turns/list" ? listExternalTurns(turns, params) : listExternalItems(turns, params);
|
|
41196
41662
|
await this.#writer.json(rpcEnvelope(request, { result }));
|
|
41663
|
+
if (request.method === "thread/turns/list") {
|
|
41664
|
+
this.#markExternalHistoryRead(thread, result.data);
|
|
41665
|
+
}
|
|
41197
41666
|
} catch (error51) {
|
|
41198
41667
|
await this.#writer.json(
|
|
41199
41668
|
rpcError(
|
|
@@ -41212,7 +41681,7 @@ var AppServerHost = class {
|
|
|
41212
41681
|
return;
|
|
41213
41682
|
}
|
|
41214
41683
|
}
|
|
41215
|
-
const turns = this.#externalHistoryTurns(thread);
|
|
41684
|
+
const turns = [...this.#externalHistoryTurns(thread)];
|
|
41216
41685
|
const responseThread = {
|
|
41217
41686
|
...await this.#withExternalSection(thread.thread),
|
|
41218
41687
|
turns: params.excludeTurns === true ? [] : turns
|
|
@@ -41244,6 +41713,8 @@ var AppServerHost = class {
|
|
|
41244
41713
|
}
|
|
41245
41714
|
})
|
|
41246
41715
|
);
|
|
41716
|
+
if (params.excludeTurns !== true) this.#markExternalHistoryRead(thread, turns);
|
|
41717
|
+
else if (initialTurnsPage) this.#markExternalHistoryRead(thread, initialTurnsPage.data);
|
|
41247
41718
|
} catch (error51) {
|
|
41248
41719
|
await this.#writer.json(
|
|
41249
41720
|
rpcError(
|
|
@@ -41386,10 +41857,15 @@ var AppServerHost = class {
|
|
|
41386
41857
|
assertActive,
|
|
41387
41858
|
typeof requestObject(request).clientUserMessageId === "string" ? requestObject(request).clientUserMessageId : void 0,
|
|
41388
41859
|
requestObject(request)[THREAD_REFERENCE_SOURCE_HOST_PARAM]
|
|
41389
|
-
)
|
|
41860
|
+
),
|
|
41861
|
+
(input) => this.#insertExternalInput(thread, input)
|
|
41390
41862
|
);
|
|
41391
41863
|
try {
|
|
41392
|
-
await this.#writer.json(
|
|
41864
|
+
await this.#writer.json(
|
|
41865
|
+
rpcEnvelope(request, {
|
|
41866
|
+
result: { turnId: started.turnId, delivery: started.delivery }
|
|
41867
|
+
})
|
|
41868
|
+
);
|
|
41393
41869
|
} finally {
|
|
41394
41870
|
started.gate.resolve();
|
|
41395
41871
|
}
|
|
@@ -41405,6 +41881,34 @@ var AppServerHost = class {
|
|
|
41405
41881
|
this.#signalActiveWorkChanged();
|
|
41406
41882
|
}
|
|
41407
41883
|
}
|
|
41884
|
+
/** Native same-Turn input; `insertNativeSteer` owns the delivery and its fallback signal. */
|
|
41885
|
+
async #insertExternalInput(thread, input) {
|
|
41886
|
+
await insertNativeSteer(thread, input, {
|
|
41887
|
+
project: async (turnId, item, clientUserMessageId) => {
|
|
41888
|
+
const projection = this.#projectedTurn(thread, turnId);
|
|
41889
|
+
if (clientUserMessageId) {
|
|
41890
|
+
projection.projector.bindUserMessageClientId(item.itemId, clientUserMessageId);
|
|
41891
|
+
}
|
|
41892
|
+
await this.#projectHarnessOutput(thread, {
|
|
41893
|
+
kind: "event",
|
|
41894
|
+
event: { type: "item.started", turnId, item }
|
|
41895
|
+
});
|
|
41896
|
+
await this.#projectHarnessOutput(thread, {
|
|
41897
|
+
kind: "event",
|
|
41898
|
+
event: {
|
|
41899
|
+
type: "item.completed",
|
|
41900
|
+
turnId,
|
|
41901
|
+
snapshot: { item, outcome: { status: "succeeded" } }
|
|
41902
|
+
}
|
|
41903
|
+
});
|
|
41904
|
+
},
|
|
41905
|
+
diagnose: (error51) => this.#diagnose(error51)
|
|
41906
|
+
});
|
|
41907
|
+
return {
|
|
41908
|
+
turnId: input.turnId,
|
|
41909
|
+
gate: { promise: Promise.resolve(), resolve: () => void 0 }
|
|
41910
|
+
};
|
|
41911
|
+
}
|
|
41408
41912
|
/** Keep command restoration and dispatch identical for start and steer submissions. */
|
|
41409
41913
|
async #beginExternalInputTurn(thread, inputText, assertActive, clientUserMessageId, sourceHostId) {
|
|
41410
41914
|
const text = restoreHarnessCommandMentions(inputText);
|
|
@@ -41462,7 +41966,7 @@ var AppServerHost = class {
|
|
|
41462
41966
|
if (thread.running || thread.activeTurnId || this.#pendingExternalCommandRequests.has(thread.id)) {
|
|
41463
41967
|
throw new ExternalSteerError(-32072, "External Thread already has an active Turn");
|
|
41464
41968
|
}
|
|
41465
|
-
const turnId = hostTurnIdSchema.parse(
|
|
41969
|
+
const turnId = hostTurnIdSchema.parse(randomUUID16());
|
|
41466
41970
|
const startedAtMs = Date.now();
|
|
41467
41971
|
const projection = {
|
|
41468
41972
|
projector: new CodexTurnProjector({
|
|
@@ -41757,6 +42261,9 @@ var AppServerHost = class {
|
|
|
41757
42261
|
}
|
|
41758
42262
|
return;
|
|
41759
42263
|
}
|
|
42264
|
+
if (event.type === "turn.completed" && thread.pendingSteerProjections.size > 0) {
|
|
42265
|
+
await Promise.allSettled([...thread.pendingSteerProjections]);
|
|
42266
|
+
}
|
|
41760
42267
|
const projection = this.#projectedTurn(thread, event.turnId);
|
|
41761
42268
|
await this.#waitForTurnResponse(thread, event.turnId);
|
|
41762
42269
|
if (event.type === "interaction.closed" && thread.ignoredInteractionIds.delete(event.interactionId)) {
|
|
@@ -41806,6 +42313,7 @@ var AppServerHost = class {
|
|
|
41806
42313
|
thread.activeTurnId = null;
|
|
41807
42314
|
if (!projection.projector.hasOpenDetachedItems) thread.projectedTurns.delete(event.turnId);
|
|
41808
42315
|
thread.responseGates.delete(event.turnId);
|
|
42316
|
+
thread.pendingSteerProjections.clear();
|
|
41809
42317
|
this.#signalActiveWorkChanged();
|
|
41810
42318
|
const delegation = await this.#repository.getDelegationByChild(thread.record.hostThreadId);
|
|
41811
42319
|
if (delegation) {
|
|
@@ -42096,7 +42604,7 @@ var AppServerHost = class {
|
|
|
42096
42604
|
try {
|
|
42097
42605
|
result = projection.projector.projectQuestion(
|
|
42098
42606
|
interaction,
|
|
42099
|
-
hostItemIdSchema.parse(
|
|
42607
|
+
hostItemIdSchema.parse(randomUUID16())
|
|
42100
42608
|
);
|
|
42101
42609
|
} catch (error51) {
|
|
42102
42610
|
this.#diagnose(error51);
|
|
@@ -42335,7 +42843,7 @@ var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
|
42335
42843
|
var wrapper_default = import_websocket.default;
|
|
42336
42844
|
|
|
42337
42845
|
// packages/host-runtime/src/remote-socket-lock.ts
|
|
42338
|
-
import { randomUUID as
|
|
42846
|
+
import { randomUUID as randomUUID17 } from "node:crypto";
|
|
42339
42847
|
import { chmod as chmod3, lstat as lstat5, mkdir as mkdir12, open as open9, readFile as readFile16, readdir as readdir5, rename as rename11, rm as rm11 } from "node:fs/promises";
|
|
42340
42848
|
import { uptime } from "node:os";
|
|
42341
42849
|
import path26 from "node:path";
|
|
@@ -42461,7 +42969,7 @@ async function preparePrivateLockDirectory(lockDirectory) {
|
|
|
42461
42969
|
await chmod3(lockDirectory, 448);
|
|
42462
42970
|
}
|
|
42463
42971
|
async function writeLockRecordAtomic(lockDirectory, entryPath, record4) {
|
|
42464
|
-
const temporary = path26.join(lockDirectory, `.tmp-${record4.ownerToken}-${
|
|
42972
|
+
const temporary = path26.join(lockDirectory, `.tmp-${record4.ownerToken}-${randomUUID17()}`);
|
|
42465
42973
|
const handle = await open9(temporary, "wx", 384);
|
|
42466
42974
|
try {
|
|
42467
42975
|
await handle.writeFile(`${JSON.stringify(record4)}
|
|
@@ -42536,7 +43044,7 @@ async function withRemoteAppServerSocketInitializationLock(socketPath, action) {
|
|
|
42536
43044
|
const legacyPath = `${socketPath}.initializing`;
|
|
42537
43045
|
const lockDirectory = `${socketPath}.initializers`;
|
|
42538
43046
|
await preparePrivateLockDirectory(lockDirectory);
|
|
42539
|
-
const ownerToken =
|
|
43047
|
+
const ownerToken = randomUUID17();
|
|
42540
43048
|
const entryPath = path26.join(lockDirectory, lockEntryName(ownerToken));
|
|
42541
43049
|
const baseRecord = {
|
|
42542
43050
|
version: 2,
|
|
@@ -43047,12 +43555,12 @@ function createRemoteAppServerWebSocketListener(input) {
|
|
|
43047
43555
|
|
|
43048
43556
|
// packages/host-runtime/src/remote-official-app-server.ts
|
|
43049
43557
|
import { spawn as spawn5 } from "node:child_process";
|
|
43050
|
-
import { randomUUID as
|
|
43558
|
+
import { randomUUID as randomUUID18 } from "node:crypto";
|
|
43051
43559
|
import { lstat as lstat7, rm as rm13, stat as stat7 } from "node:fs/promises";
|
|
43052
43560
|
import path28 from "node:path";
|
|
43053
43561
|
var DEFAULT_CLOSE_TIMEOUT_MS = 2e3;
|
|
43054
43562
|
var DEFAULT_LISTEN_TIMEOUT_MS = 1e4;
|
|
43055
|
-
function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token =
|
|
43563
|
+
function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token = randomUUID18()) {
|
|
43056
43564
|
if (!path28.posix.isAbsolute(desktopControlSocketPath)) {
|
|
43057
43565
|
throw new Error("Desktop control socket path must be absolute");
|
|
43058
43566
|
}
|
|
@@ -44271,11 +44779,11 @@ async function readRemoteDelegationThread(environment, input) {
|
|
|
44271
44779
|
}
|
|
44272
44780
|
|
|
44273
44781
|
// packages/host-runtime/src/shared-thread-owner.ts
|
|
44274
|
-
import { randomUUID as
|
|
44782
|
+
import { randomUUID as randomUUID20 } from "node:crypto";
|
|
44275
44783
|
import { PassThrough as PassThrough3 } from "node:stream";
|
|
44276
44784
|
|
|
44277
44785
|
// packages/host-runtime/src/shared-thread-peer.ts
|
|
44278
|
-
import { randomUUID as
|
|
44786
|
+
import { randomUUID as randomUUID19 } from "node:crypto";
|
|
44279
44787
|
function object5(value2) {
|
|
44280
44788
|
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
44281
44789
|
}
|
|
@@ -44289,7 +44797,7 @@ var StreamThreadPeer = class {
|
|
|
44289
44797
|
input;
|
|
44290
44798
|
output;
|
|
44291
44799
|
stop;
|
|
44292
|
-
#prefix = `shared:${
|
|
44800
|
+
#prefix = `shared:${randomUUID19()}:`;
|
|
44293
44801
|
#pending = /* @__PURE__ */ new Map();
|
|
44294
44802
|
#listeners = /* @__PURE__ */ new Set();
|
|
44295
44803
|
#ended = Promise.withResolvers();
|
|
@@ -44367,7 +44875,7 @@ var SharedThreadOwner = class {
|
|
|
44367
44875
|
input = new PassThrough3();
|
|
44368
44876
|
output = new PassThrough3();
|
|
44369
44877
|
#peer = new StreamThreadPeer(this.output, this.input, () => this.input.end());
|
|
44370
|
-
#prefix = `shared-interaction:${
|
|
44878
|
+
#prefix = `shared-interaction:${randomUUID20()}:`;
|
|
44371
44879
|
#interactions = /* @__PURE__ */ new Map();
|
|
44372
44880
|
#listeners = /* @__PURE__ */ new Set();
|
|
44373
44881
|
#receipts = /* @__PURE__ */ new Map();
|
|
@@ -44677,7 +45185,7 @@ var SharedThreadBridge = class {
|
|
|
44677
45185
|
};
|
|
44678
45186
|
|
|
44679
45187
|
// packages/host-runtime/src/remote-control-app-server.ts
|
|
44680
|
-
import { randomUUID as
|
|
45188
|
+
import { randomUUID as randomUUID21 } from "node:crypto";
|
|
44681
45189
|
import { mkdir as mkdir15, open as open10, rename as rename12, rm as rm14 } from "node:fs/promises";
|
|
44682
45190
|
import path33 from "node:path";
|
|
44683
45191
|
var REMOTE_CONTROL_BRIDGE_PIPE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_PIPE";
|
|
@@ -44698,7 +45206,7 @@ function nodeCompatibleWindowsPath(value2) {
|
|
|
44698
45206
|
if (value2.startsWith("\\\\?\\")) return value2.slice(4);
|
|
44699
45207
|
return value2;
|
|
44700
45208
|
}
|
|
44701
|
-
function remoteControlBridgePipePath(processId = process.pid, instanceId =
|
|
45209
|
+
function remoteControlBridgePipePath(processId = process.pid, instanceId = randomUUID21()) {
|
|
44702
45210
|
const safeInstance = instanceId.replaceAll(/[^a-zA-Z0-9-]/gu, "");
|
|
44703
45211
|
if (!safeInstance) throw new Error("Remote Control bridge instance ID is invalid");
|
|
44704
45212
|
return `\\\\.\\pipe\\codexhost-remote-control-${processId}-${safeInstance}`;
|
|
@@ -44713,7 +45221,7 @@ async function publishRemoteControlAppServerDescriptor(plan) {
|
|
|
44713
45221
|
await mkdir15(directory, { recursive: true, mode: 448 });
|
|
44714
45222
|
const temporaryPath = path33.join(
|
|
44715
45223
|
directory,
|
|
44716
|
-
`.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${
|
|
45224
|
+
`.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${randomUUID21()}.tmp`
|
|
44717
45225
|
);
|
|
44718
45226
|
const handle = await open10(temporaryPath, "wx", 384);
|
|
44719
45227
|
try {
|
|
@@ -45235,12 +45743,19 @@ function createHostUpdateCoordinator(options2) {
|
|
|
45235
45743
|
}
|
|
45236
45744
|
|
|
45237
45745
|
// packages/host-runtime/src/usage-statistics.ts
|
|
45238
|
-
import { randomUUID as
|
|
45746
|
+
import { randomUUID as randomUUID22 } from "node:crypto";
|
|
45239
45747
|
import { mkdir as mkdir17, readFile as readFile17, readdir as readdir6, rename as rename14, rm as rm16, writeFile as writeFile10 } from "node:fs/promises";
|
|
45240
45748
|
import path36 from "node:path";
|
|
45241
45749
|
import { setImmediate as yieldToEventLoop } from "node:timers/promises";
|
|
45242
45750
|
|
|
45243
45751
|
// packages/harness-adapter/dist/usage-statistics.js
|
|
45752
|
+
var HarnessUsageSourceChangedError = class extends Error {
|
|
45753
|
+
code = "HARNESS_USAGE_SOURCE_CHANGED";
|
|
45754
|
+
/** Plugins may bundle their own copy of this contract, so instanceof is insufficient. */
|
|
45755
|
+
static is(error51) {
|
|
45756
|
+
return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "HARNESS_USAGE_SOURCE_CHANGED";
|
|
45757
|
+
}
|
|
45758
|
+
};
|
|
45244
45759
|
var MAX_SESSION_ID_LENGTH = 512;
|
|
45245
45760
|
var MAX_CWD_LENGTH = 4096;
|
|
45246
45761
|
var MAX_SESSION_TITLE_LENGTH = 200;
|
|
@@ -45252,10 +45767,13 @@ function usageSessionTitle(value2) {
|
|
|
45252
45767
|
return void 0;
|
|
45253
45768
|
if (normalized.length <= MAX_SESSION_TITLE_LENGTH)
|
|
45254
45769
|
return normalized;
|
|
45255
|
-
|
|
45256
|
-
|
|
45257
|
-
|
|
45258
|
-
|
|
45770
|
+
let title = "";
|
|
45771
|
+
for (const character of normalized) {
|
|
45772
|
+
if (title.length + character.length >= MAX_SESSION_TITLE_LENGTH)
|
|
45773
|
+
break;
|
|
45774
|
+
title += character;
|
|
45775
|
+
}
|
|
45776
|
+
return `${title.trimEnd()}…`;
|
|
45259
45777
|
}
|
|
45260
45778
|
function sessionIdOk(value2) {
|
|
45261
45779
|
return typeof value2 === "string" && value2.length > 0 && value2.length <= MAX_SESSION_ID_LENGTH;
|
|
@@ -45340,6 +45858,95 @@ function withHostSessionTitles(result, records) {
|
|
|
45340
45858
|
};
|
|
45341
45859
|
}
|
|
45342
45860
|
|
|
45861
|
+
// packages/host-runtime/src/usage-statistics-sources.ts
|
|
45862
|
+
import { setTimeout as delay6 } from "node:timers/promises";
|
|
45863
|
+
async function* readUsageStatisticsSources(capability, sources, signal) {
|
|
45864
|
+
let pending = sources;
|
|
45865
|
+
for (let attempt = 0; ; attempt++) {
|
|
45866
|
+
const changed = [];
|
|
45867
|
+
for (const source of pending) {
|
|
45868
|
+
signal.throwIfAborted();
|
|
45869
|
+
try {
|
|
45870
|
+
const entries = (await capability.readSource(source.id, signal)).map(parseHarnessUsageEntry).filter((entry) => entry !== null);
|
|
45871
|
+
yield { source, entries };
|
|
45872
|
+
} catch (error51) {
|
|
45873
|
+
signal.throwIfAborted();
|
|
45874
|
+
if (HarnessUsageSourceChangedError.is(error51) && attempt < 2) changed.push(source);
|
|
45875
|
+
else yield { source, error: error51 };
|
|
45876
|
+
}
|
|
45877
|
+
}
|
|
45878
|
+
if (!changed.length) return;
|
|
45879
|
+
await delay6(50 * (attempt + 1), void 0, { signal });
|
|
45880
|
+
let current;
|
|
45881
|
+
try {
|
|
45882
|
+
current = new Map(
|
|
45883
|
+
(await capability.listSources(signal)).map((source) => [source.id, source])
|
|
45884
|
+
);
|
|
45885
|
+
} catch (error51) {
|
|
45886
|
+
signal.throwIfAborted();
|
|
45887
|
+
for (const source of changed) yield { source, error: error51 };
|
|
45888
|
+
return;
|
|
45889
|
+
}
|
|
45890
|
+
const next = [];
|
|
45891
|
+
for (const source of changed) {
|
|
45892
|
+
const fresh = current.get(source.id);
|
|
45893
|
+
if (fresh) next.push(fresh);
|
|
45894
|
+
else yield { source, removed: true };
|
|
45895
|
+
}
|
|
45896
|
+
pending = next;
|
|
45897
|
+
}
|
|
45898
|
+
}
|
|
45899
|
+
|
|
45900
|
+
// packages/host-runtime/src/usage-statistics-calendar.ts
|
|
45901
|
+
function dateKey(year, month, day) {
|
|
45902
|
+
return `${year}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
|
|
45903
|
+
}
|
|
45904
|
+
function createUsageStatisticsCalendar(timeZone) {
|
|
45905
|
+
const localZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
45906
|
+
const zone = timeZone ?? localZone;
|
|
45907
|
+
if (zone === localZone) {
|
|
45908
|
+
return {
|
|
45909
|
+
timeZone: zone,
|
|
45910
|
+
at(ms) {
|
|
45911
|
+
const date5 = new Date(ms);
|
|
45912
|
+
return {
|
|
45913
|
+
date: dateKey(date5.getFullYear(), date5.getMonth() + 1, date5.getDate()),
|
|
45914
|
+
weekday: date5.getDay(),
|
|
45915
|
+
hour: date5.getHours()
|
|
45916
|
+
};
|
|
45917
|
+
}
|
|
45918
|
+
};
|
|
45919
|
+
}
|
|
45920
|
+
const format = new Intl.DateTimeFormat("en-US", {
|
|
45921
|
+
timeZone: zone,
|
|
45922
|
+
calendar: "gregory",
|
|
45923
|
+
numberingSystem: "latn",
|
|
45924
|
+
year: "numeric",
|
|
45925
|
+
month: "2-digit",
|
|
45926
|
+
day: "2-digit",
|
|
45927
|
+
hour: "2-digit",
|
|
45928
|
+
hourCycle: "h23"
|
|
45929
|
+
});
|
|
45930
|
+
return {
|
|
45931
|
+
timeZone: zone,
|
|
45932
|
+
at(ms) {
|
|
45933
|
+
const parts = format.formatToParts(ms);
|
|
45934
|
+
const part = (type) => Number(parts.find((value2) => value2.type === type)?.value);
|
|
45935
|
+
const year = part("year"), month = part("month"), day = part("day");
|
|
45936
|
+
return {
|
|
45937
|
+
date: dateKey(year, month, day),
|
|
45938
|
+
weekday: new Date(Date.UTC(year, month - 1, day)).getUTCDay(),
|
|
45939
|
+
hour: part("hour")
|
|
45940
|
+
};
|
|
45941
|
+
}
|
|
45942
|
+
};
|
|
45943
|
+
}
|
|
45944
|
+
function shiftUsageDate(date5, days) {
|
|
45945
|
+
const value2 = /* @__PURE__ */ new Date(`${date5}T12:00:00Z`);
|
|
45946
|
+
value2.setUTCDate(value2.getUTCDate() + days);
|
|
45947
|
+
return dateKey(value2.getUTCFullYear(), value2.getUTCMonth() + 1, value2.getUTCDate());
|
|
45948
|
+
}
|
|
45949
|
+
|
|
45343
45950
|
// packages/host-runtime/src/usage-statistics.ts
|
|
45344
45951
|
var CACHE_VERSION = 7;
|
|
45345
45952
|
var STALE_AFTER_MS = 1e4;
|
|
@@ -45400,17 +46007,6 @@ function expand(value2, intern) {
|
|
|
45400
46007
|
function message(error51) {
|
|
45401
46008
|
return error51 instanceof Error ? error51.message : String(error51);
|
|
45402
46009
|
}
|
|
45403
|
-
function localDate2(ms) {
|
|
45404
|
-
const date5 = new Date(ms);
|
|
45405
|
-
const month = String(date5.getMonth() + 1).padStart(2, "0");
|
|
45406
|
-
const day = String(date5.getDate()).padStart(2, "0");
|
|
45407
|
-
return `${date5.getFullYear()}-${month}-${day}`;
|
|
45408
|
-
}
|
|
45409
|
-
function shiftDate(date5, days) {
|
|
45410
|
-
const value2 = /* @__PURE__ */ new Date(`${date5}T12:00:00`);
|
|
45411
|
-
value2.setDate(value2.getDate() + days);
|
|
45412
|
-
return localDate2(value2.getTime());
|
|
45413
|
-
}
|
|
45414
46010
|
var SESSIONS_PER_MEASURE = 50;
|
|
45415
46011
|
var MODELS_PER_SESSION = 16;
|
|
45416
46012
|
function emptyTotals() {
|
|
@@ -45597,23 +46193,27 @@ var UsageStatistics = class {
|
|
|
45597
46193
|
}
|
|
45598
46194
|
for (const { harness: harness2, capability, ids } of listed) {
|
|
45599
46195
|
const cache = this.#cache(harness2);
|
|
45600
|
-
const present =
|
|
46196
|
+
const present = new Set(ids.map(({ id: id2 }) => id2));
|
|
45601
46197
|
let failed = null;
|
|
45602
|
-
|
|
45603
|
-
|
|
45604
|
-
|
|
45605
|
-
|
|
45606
|
-
|
|
45607
|
-
|
|
46198
|
+
const pending = ids.filter(
|
|
46199
|
+
({ id: id2, fingerprint }) => cache.sources.get(id2)?.fingerprint !== fingerprint
|
|
46200
|
+
);
|
|
46201
|
+
this.#progress.read += ids.length - pending.length;
|
|
46202
|
+
try {
|
|
46203
|
+
for await (const result of readUsageStatisticsSources(capability, pending, signal)) {
|
|
46204
|
+
const { id: id2, fingerprint } = result.source;
|
|
46205
|
+
if ("entries" in result) {
|
|
46206
|
+
cache.sources.set(id2, { fingerprint, entries: result.entries });
|
|
45608
46207
|
cache.dirty = true;
|
|
45609
46208
|
this.#generation += 1;
|
|
45610
|
-
}
|
|
45611
|
-
|
|
45612
|
-
|
|
45613
|
-
}
|
|
46209
|
+
} else if ("error" in result) failed ??= message(result.error);
|
|
46210
|
+
else present.delete(id2);
|
|
46211
|
+
this.#progress.read += 1;
|
|
45614
46212
|
await yieldToEventLoop();
|
|
45615
46213
|
}
|
|
45616
|
-
|
|
46214
|
+
} catch (error51) {
|
|
46215
|
+
if (signal.aborted) return;
|
|
46216
|
+
throw error51;
|
|
45617
46217
|
}
|
|
45618
46218
|
for (const id2 of cache.sources.keys()) {
|
|
45619
46219
|
if (!present.has(id2)) {
|
|
@@ -45678,7 +46278,7 @@ var UsageStatistics = class {
|
|
|
45678
46278
|
async #persist(harness2, cache) {
|
|
45679
46279
|
if (!cache.dirty || this.#now() - cache.persistedAtMs < PERSIST_INTERVAL_MS) return;
|
|
45680
46280
|
const file2 = this.#file(harness2);
|
|
45681
|
-
const temporary = `${file2}.${
|
|
46281
|
+
const temporary = `${file2}.${randomUUID22()}.tmp`;
|
|
45682
46282
|
try {
|
|
45683
46283
|
await mkdir17(this.#directory, { recursive: true });
|
|
45684
46284
|
const sources = [...cache.sources].map(([id2, source]) => [
|
|
@@ -45696,9 +46296,10 @@ var UsageStatistics = class {
|
|
|
45696
46296
|
await rm16(temporary, { force: true });
|
|
45697
46297
|
}
|
|
45698
46298
|
}
|
|
45699
|
-
/** Every request once, per Harness in source order,
|
|
45700
|
-
#indexed() {
|
|
45701
|
-
if (this.#index?.generation === this.#generation
|
|
46299
|
+
/** Every request once, per Harness in source order, in the requested calendar. */
|
|
46300
|
+
#indexed(calendar) {
|
|
46301
|
+
if (this.#index?.generation === this.#generation && this.#index.timeZone === calendar.timeZone)
|
|
46302
|
+
return this.#index.entries;
|
|
45702
46303
|
const entries = [];
|
|
45703
46304
|
for (const [harness2, cache] of this.#caches) {
|
|
45704
46305
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -45706,26 +46307,20 @@ var UsageStatistics = class {
|
|
|
45706
46307
|
for (const entry of parsed2) {
|
|
45707
46308
|
if (seen.has(entry.id)) continue;
|
|
45708
46309
|
seen.add(entry.id);
|
|
45709
|
-
|
|
45710
|
-
entries.push({
|
|
45711
|
-
harness: harness2,
|
|
45712
|
-
entry,
|
|
45713
|
-
date: localDate2(entry.occurredAtMs),
|
|
45714
|
-
weekday: at.getDay(),
|
|
45715
|
-
hour: at.getHours()
|
|
45716
|
-
});
|
|
46310
|
+
entries.push({ harness: harness2, entry, ...calendar.at(entry.occurredAtMs) });
|
|
45717
46311
|
}
|
|
45718
46312
|
}
|
|
45719
46313
|
}
|
|
45720
|
-
this.#index = { generation: this.#generation, entries };
|
|
46314
|
+
this.#index = { generation: this.#generation, timeZone: calendar.timeZone, entries };
|
|
45721
46315
|
return entries;
|
|
45722
46316
|
}
|
|
45723
46317
|
#aggregate(params, now, lookup) {
|
|
45724
46318
|
const { range } = params;
|
|
45725
46319
|
const days = RANGE_DAYS[range];
|
|
45726
|
-
const
|
|
46320
|
+
const calendar = createUsageStatisticsCalendar(params.timeZone);
|
|
46321
|
+
const to = calendar.at(now).date;
|
|
45727
46322
|
let from = null;
|
|
45728
|
-
if (days !== null) from =
|
|
46323
|
+
if (days !== null) from = shiftUsageDate(to, -days + 1);
|
|
45729
46324
|
const inRange = (date5) => (from === null || date5 >= from) && date5 <= to;
|
|
45730
46325
|
const day = params.date !== void 0 && inRange(params.date) ? params.date : null;
|
|
45731
46326
|
const harnessFilter = params.harness ?? null;
|
|
@@ -45766,7 +46361,7 @@ var UsageStatistics = class {
|
|
|
45766
46361
|
const harnessPriced = /* @__PURE__ */ new Map();
|
|
45767
46362
|
const byProject = /* @__PURE__ */ new Map();
|
|
45768
46363
|
const sessions = /* @__PURE__ */ new Map();
|
|
45769
|
-
for (const indexed of this.#indexed()) {
|
|
46364
|
+
for (const indexed of this.#indexed(calendar)) {
|
|
45770
46365
|
const { harness: harness2, entry, date: date5 } = indexed;
|
|
45771
46366
|
if (!inRange(date5)) continue;
|
|
45772
46367
|
const model2 = entry.model ?? null;
|
|
@@ -46294,7 +46889,7 @@ async function runHostRuntime(input) {
|
|
|
46294
46889
|
}
|
|
46295
46890
|
|
|
46296
46891
|
// packages/host-runtime/src/remote-host-install.ts
|
|
46297
|
-
import { createHash as createHash11, randomUUID as
|
|
46892
|
+
import { createHash as createHash11, randomUUID as randomUUID23 } from "node:crypto";
|
|
46298
46893
|
import { constants as fsConstants } from "node:fs";
|
|
46299
46894
|
import {
|
|
46300
46895
|
access as access3,
|
|
@@ -46393,7 +46988,7 @@ async function writeAtomic(filePath, contents, mode) {
|
|
|
46393
46988
|
await mkdir18(path38.dirname(filePath), { recursive: true, mode: 448 });
|
|
46394
46989
|
const temporary = path38.join(
|
|
46395
46990
|
path38.dirname(filePath),
|
|
46396
|
-
`.${path38.basename(filePath)}.${process.pid}.${
|
|
46991
|
+
`.${path38.basename(filePath)}.${process.pid}.${randomUUID23()}.tmp`
|
|
46397
46992
|
);
|
|
46398
46993
|
try {
|
|
46399
46994
|
if (typeof contents === "string") {
|
|
@@ -46417,7 +47012,7 @@ async function writeAtomicExecutable(filePath, sourcePath) {
|
|
|
46417
47012
|
await mkdir18(path38.dirname(filePath), { recursive: true, mode: 448 });
|
|
46418
47013
|
const temporary = path38.join(
|
|
46419
47014
|
path38.dirname(filePath),
|
|
46420
|
-
`.${path38.basename(filePath)}.${process.pid}.${
|
|
47015
|
+
`.${path38.basename(filePath)}.${process.pid}.${randomUUID23()}.tmp`
|
|
46421
47016
|
);
|
|
46422
47017
|
try {
|
|
46423
47018
|
await copyFile4(sourcePath, temporary);
|
|
@@ -47158,6 +47753,7 @@ var harnessBrokerMethodSchema = external_exports.enum([
|
|
|
47158
47753
|
"adapter.open",
|
|
47159
47754
|
"adapter.subagent.readSnapshot",
|
|
47160
47755
|
"session.readSnapshot",
|
|
47756
|
+
"session.readCapabilities",
|
|
47161
47757
|
"session.refreshUsage",
|
|
47162
47758
|
"session.execute",
|
|
47163
47759
|
"session.commands.list",
|
|
@@ -47340,6 +47936,11 @@ var turnStartSchema = external_exports.object({
|
|
|
47340
47936
|
turnId: hostTurnIdSchema,
|
|
47341
47937
|
input: external_exports.array(textInputSchema)
|
|
47342
47938
|
}).strict();
|
|
47939
|
+
var turnSteerSchema = external_exports.object({
|
|
47940
|
+
type: external_exports.literal("turn.steer"),
|
|
47941
|
+
turnId: hostTurnIdSchema,
|
|
47942
|
+
input: external_exports.array(textInputSchema)
|
|
47943
|
+
}).strict();
|
|
47343
47944
|
var turnCancelSchema = external_exports.object({ type: external_exports.literal("turn.cancel"), turnId: hostTurnIdSchema }).strict();
|
|
47344
47945
|
var interactionResponseSchema = external_exports.union([
|
|
47345
47946
|
external_exports.object({
|
|
@@ -47365,6 +47966,7 @@ var permissionSelectSchema = external_exports.object({
|
|
|
47365
47966
|
}).strict();
|
|
47366
47967
|
var brokerHostCommandSchema = external_exports.discriminatedUnion("type", [
|
|
47367
47968
|
turnStartSchema,
|
|
47969
|
+
turnSteerSchema,
|
|
47368
47970
|
turnCancelSchema,
|
|
47369
47971
|
interactionRespondSchema,
|
|
47370
47972
|
modelSelectSchema,
|
|
@@ -47499,7 +48101,7 @@ var harnessOutputSchema = external_exports.custom((value2) => {
|
|
|
47499
48101
|
});
|
|
47500
48102
|
|
|
47501
48103
|
// packages/harness-broker/dist/server.js
|
|
47502
|
-
import { randomBytes as randomBytes5, randomUUID as
|
|
48104
|
+
import { randomBytes as randomBytes5, randomUUID as randomUUID24 } from "node:crypto";
|
|
47503
48105
|
import { chmod as chmod6, lstat as lstat10, mkdir as mkdir19, open as open11, readFile as readFile19, rename as rename16, rm as rm18 } from "node:fs/promises";
|
|
47504
48106
|
import net4, {} from "node:net";
|
|
47505
48107
|
import path41 from "node:path";
|
|
@@ -47558,7 +48160,7 @@ async function assertNoLiveDescriptor(descriptorPath) {
|
|
|
47558
48160
|
}
|
|
47559
48161
|
}
|
|
47560
48162
|
async function publishDescriptor(descriptorPath, descriptor) {
|
|
47561
|
-
const temporary = `${descriptorPath}.${process.pid}.${
|
|
48163
|
+
const temporary = `${descriptorPath}.${process.pid}.${randomUUID24()}.tmp`;
|
|
47562
48164
|
const handle = await open11(temporary, "wx", 384);
|
|
47563
48165
|
try {
|
|
47564
48166
|
await handle.writeFile(`${JSON.stringify(descriptor)}
|
|
@@ -47583,6 +48185,7 @@ function sessionMetadata(record4) {
|
|
|
47583
48185
|
sessionId: record4.id,
|
|
47584
48186
|
sessionGeneration: record4.generation,
|
|
47585
48187
|
capabilities: record4.session.capabilities,
|
|
48188
|
+
readCapabilities: true,
|
|
47586
48189
|
initialState: {
|
|
47587
48190
|
...initialState,
|
|
47588
48191
|
...record4.nativeRef ? { nativeRef: record4.nativeRef } : {},
|
|
@@ -47635,7 +48238,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
47635
48238
|
await assertNoLiveDescriptor(input.descriptorPath);
|
|
47636
48239
|
if (process.platform !== "win32")
|
|
47637
48240
|
await prepareUnixSocketPath(input.socketPath);
|
|
47638
|
-
const generation = input.generation ??
|
|
48241
|
+
const generation = input.generation ?? randomUUID24();
|
|
47639
48242
|
const token = input.token ?? randomBytes5(32).toString("hex");
|
|
47640
48243
|
const descriptor = {
|
|
47641
48244
|
schemaVersion: 1,
|
|
@@ -47676,7 +48279,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
47676
48279
|
};
|
|
47677
48280
|
const server = net4.createServer((socket) => {
|
|
47678
48281
|
const state = {
|
|
47679
|
-
id:
|
|
48282
|
+
id: randomUUID24(),
|
|
47680
48283
|
socket,
|
|
47681
48284
|
authenticated: false,
|
|
47682
48285
|
inputSequence: 0,
|
|
@@ -47853,8 +48456,11 @@ async function startHarnessBrokerServer(input) {
|
|
|
47853
48456
|
retireWhenIdle = false;
|
|
47854
48457
|
if (request.method === "adapter.credits") {
|
|
47855
48458
|
harnessAccountListParamsSchema.parse(request.params);
|
|
47856
|
-
const
|
|
47857
|
-
|
|
48459
|
+
const value2 = input.adapter.credits?.();
|
|
48460
|
+
const credits = parseHarnessAccountCredits(value2);
|
|
48461
|
+
if (value2 != null && !credits)
|
|
48462
|
+
throw new Error("Invalid account credits snapshot");
|
|
48463
|
+
return credits;
|
|
47858
48464
|
}
|
|
47859
48465
|
if (request.method === "adapter.inspectAccount") {
|
|
47860
48466
|
harnessAccountListParamsSchema.parse(request.params);
|
|
@@ -47911,7 +48517,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
47911
48517
|
}
|
|
47912
48518
|
};
|
|
47913
48519
|
}
|
|
47914
|
-
const openReservation =
|
|
48520
|
+
const openReservation = randomUUID24();
|
|
47915
48521
|
if (sourceKey)
|
|
47916
48522
|
nativeWriters.set(sourceKey, openReservation);
|
|
47917
48523
|
const provisionalReservation = openInput.kind === "create" ? openReservation : void 0;
|
|
@@ -48055,6 +48661,8 @@ async function startHarnessBrokerServer(input) {
|
|
|
48055
48661
|
let result;
|
|
48056
48662
|
if (command.type === "turn.start")
|
|
48057
48663
|
result = await record5.session.execute(command);
|
|
48664
|
+
else if (command.type === "turn.steer")
|
|
48665
|
+
result = await record5.session.execute(command);
|
|
48058
48666
|
else if (command.type === "turn.cancel")
|
|
48059
48667
|
result = await record5.session.execute(command);
|
|
48060
48668
|
else if (command.type === "interaction.respond") {
|
|
@@ -48086,6 +48694,10 @@ async function startHarnessBrokerServer(input) {
|
|
|
48086
48694
|
}
|
|
48087
48695
|
return result;
|
|
48088
48696
|
}
|
|
48697
|
+
if (request.method === "session.readCapabilities") {
|
|
48698
|
+
const session = requireSession(request.params).session;
|
|
48699
|
+
return session.readCapabilities ? session.readCapabilities() : session.capabilities;
|
|
48700
|
+
}
|
|
48089
48701
|
if (request.method === "session.readSnapshot") {
|
|
48090
48702
|
return requireSession(request.params).session.readSnapshot();
|
|
48091
48703
|
}
|
|
@@ -48212,7 +48824,7 @@ async function startHarnessBrokerServer(input) {
|
|
|
48212
48824
|
}
|
|
48213
48825
|
state.authenticated = true;
|
|
48214
48826
|
state.inputSequence = 1;
|
|
48215
|
-
await send({ kind: "response", id:
|
|
48827
|
+
await send({ kind: "response", id: randomUUID24(), ok: true, value: { ready: true } });
|
|
48216
48828
|
return;
|
|
48217
48829
|
}
|
|
48218
48830
|
const parsed2 = harnessBrokerRequestSchema.safeParse(raw);
|