@yu_robotics/remote-cli 1.6.173 → 1.6.177

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.
Files changed (79) hide show
  1. package/README.md +24 -3
  2. package/dist/client/MessageHandler.d.ts +2 -0
  3. package/dist/client/MessageHandler.d.ts.map +1 -1
  4. package/dist/client/MessageHandler.js +73 -18
  5. package/dist/client/MessageHandler.js.map +1 -1
  6. package/dist/client/WebSocketClient.d.ts.map +1 -1
  7. package/dist/client/WebSocketClient.js +1 -0
  8. package/dist/client/WebSocketClient.js.map +1 -1
  9. package/dist/delegation/DelegatedWorkerSessionStore.d.ts +11 -1
  10. package/dist/delegation/DelegatedWorkerSessionStore.d.ts.map +1 -1
  11. package/dist/delegation/DelegatedWorkerSessionStore.js +98 -51
  12. package/dist/delegation/DelegatedWorkerSessionStore.js.map +1 -1
  13. package/dist/delegation/DelegationManager.d.ts +2 -0
  14. package/dist/delegation/DelegationManager.d.ts.map +1 -1
  15. package/dist/delegation/DelegationManager.js +12 -1
  16. package/dist/delegation/DelegationManager.js.map +1 -1
  17. package/dist/executor/AcpExecutor.d.ts +6 -0
  18. package/dist/executor/AcpExecutor.d.ts.map +1 -1
  19. package/dist/executor/AcpExecutor.js +81 -10
  20. package/dist/executor/AcpExecutor.js.map +1 -1
  21. package/dist/executor/CodexAppServerClient.d.ts +2 -1
  22. package/dist/executor/CodexAppServerClient.d.ts.map +1 -1
  23. package/dist/executor/CodexAppServerClient.js +15 -11
  24. package/dist/executor/CodexAppServerClient.js.map +1 -1
  25. package/dist/executor/CodexAppServerExecutor.d.ts +12 -1
  26. package/dist/executor/CodexAppServerExecutor.d.ts.map +1 -1
  27. package/dist/executor/CodexAppServerExecutor.js +197 -4
  28. package/dist/executor/CodexAppServerExecutor.js.map +1 -1
  29. package/dist/executor/IExecutor.d.ts +19 -0
  30. package/dist/executor/IExecutor.d.ts.map +1 -1
  31. package/dist/executor/KimiExecutor.d.ts +9 -0
  32. package/dist/executor/KimiExecutor.d.ts.map +1 -1
  33. package/dist/executor/KimiExecutor.js +45 -0
  34. package/dist/executor/KimiExecutor.js.map +1 -1
  35. package/dist/executor/PiExecutor.d.ts.map +1 -1
  36. package/dist/executor/PiExecutor.js +2 -1
  37. package/dist/executor/PiExecutor.js.map +1 -1
  38. package/dist/executor/index.d.ts +2 -1
  39. package/dist/executor/index.d.ts.map +1 -1
  40. package/dist/executor/index.js +1 -0
  41. package/dist/executor/index.js.map +1 -1
  42. package/dist/executor/kimi/KimiAccountUsage.d.ts +2 -6
  43. package/dist/executor/kimi/KimiAccountUsage.d.ts.map +1 -1
  44. package/dist/executor/kimi/KimiAccountUsage.js +11 -71
  45. package/dist/executor/kimi/KimiAccountUsage.js.map +1 -1
  46. package/dist/executor/kimi/KimiLocalServer.d.ts +28 -0
  47. package/dist/executor/kimi/KimiLocalServer.d.ts.map +1 -0
  48. package/dist/executor/kimi/KimiLocalServer.js +192 -0
  49. package/dist/executor/kimi/KimiLocalServer.js.map +1 -0
  50. package/dist/executor/kimi/KimiModelCatalog.d.ts +6 -0
  51. package/dist/executor/kimi/KimiModelCatalog.d.ts.map +1 -0
  52. package/dist/executor/kimi/KimiModelCatalog.js +86 -0
  53. package/dist/executor/kimi/KimiModelCatalog.js.map +1 -0
  54. package/dist/maintenance/release-notes.json +1 -1
  55. package/dist/settings/SettingsCatalog.d.ts +1 -1
  56. package/dist/settings/SettingsCatalog.d.ts.map +1 -1
  57. package/dist/settings/SettingsCatalog.js +6 -2
  58. package/dist/settings/SettingsCatalog.js.map +1 -1
  59. package/dist/settings/SettingsService.d.ts +3 -1
  60. package/dist/settings/SettingsService.d.ts.map +1 -1
  61. package/dist/settings/SettingsService.js +17 -5
  62. package/dist/settings/SettingsService.js.map +1 -1
  63. package/dist/thread/ThreadContextReset.d.ts +12 -0
  64. package/dist/thread/ThreadContextReset.d.ts.map +1 -0
  65. package/dist/thread/ThreadContextReset.js +59 -0
  66. package/dist/thread/ThreadContextReset.js.map +1 -0
  67. package/dist/thread/ThreadExecutorPool.d.ts +11 -2
  68. package/dist/thread/ThreadExecutorPool.d.ts.map +1 -1
  69. package/dist/thread/ThreadExecutorPool.js +97 -2
  70. package/dist/thread/ThreadExecutorPool.js.map +1 -1
  71. package/dist/thread/ThreadManager.d.ts +3 -1
  72. package/dist/thread/ThreadManager.d.ts.map +1 -1
  73. package/dist/thread/ThreadManager.js +3 -0
  74. package/dist/thread/ThreadManager.js.map +1 -1
  75. package/dist/thread/types.d.ts +2 -0
  76. package/dist/thread/types.d.ts.map +1 -1
  77. package/dist/types/Settings.d.ts +8 -0
  78. package/dist/types/Settings.d.ts.map +1 -1
  79. package/package.json +1 -1
@@ -123,6 +123,9 @@ class CodexAppServerExecutor {
123
123
  currentWorkingDirectory;
124
124
  model;
125
125
  effort;
126
+ speed;
127
+ /** Only a fresh legacy thread is known not to carry an older remote speed override. */
128
+ legacyFollowReady = false;
126
129
  reportedModel;
127
130
  reportedEffort;
128
131
  autoApprove;
@@ -166,6 +169,7 @@ class CodexAppServerExecutor {
166
169
  constructor(directoryGuard, options = {}) {
167
170
  this.directoryGuard = directoryGuard;
168
171
  this.model = options.model;
172
+ this.speed = options.speed;
169
173
  this.effort = options.effort;
170
174
  this.autoApprove = options.autoApprove ?? true;
171
175
  this.remoteThreadId = options.threadId;
@@ -224,6 +228,7 @@ class CodexAppServerExecutor {
224
228
  // leave the executor busy without an actual app-server turn.
225
229
  const sandboxOptions = this.sandbox.turnOptions(this.currentWorkingDirectory);
226
230
  const input = await this.buildInput(prompt, options.attachments, temporaryFiles);
231
+ const speedOptions = await this.speedOptions();
227
232
  if (this.isBusy()) {
228
233
  await this.cleanupTemporaryFiles(temporaryFiles);
229
234
  return { success: false, error: 'Codex thread is already running a command' };
@@ -256,6 +261,7 @@ class CodexAppServerExecutor {
256
261
  cwd: this.currentWorkingDirectory,
257
262
  ...(this.model ? { model: this.model } : {}),
258
263
  ...(this.effort ? { effort: this.effort } : {}),
264
+ ...speedOptions,
259
265
  ...(this.autoApprove ? {
260
266
  approvalPolicy: 'never',
261
267
  sandboxPolicy: { type: 'dangerFullAccess' },
@@ -392,9 +398,14 @@ class CodexAppServerExecutor {
392
398
  return;
393
399
  // Native continuations bypass turn/start, so their settings must be sticky.
394
400
  const goalPolicy = this.sandbox.turnOptions(this.currentWorkingDirectory);
395
- if (this.model || this.effort || Object.keys(goalPolicy).length) {
401
+ if (this.model || this.effort || this.speed !== undefined || Object.keys(goalPolicy).length) {
402
+ const speedOptions = await this.speedOptions();
403
+ this.assertGoalOwner(run);
404
+ if (run.controlling)
405
+ return;
396
406
  await this.goalRequest('thread/settings/update', { threadId: this.codexThreadId,
397
- ...(this.model ? { model: this.model } : {}), ...(this.effort ? { effort: this.effort } : {}), ...goalPolicy });
407
+ ...(this.model ? { model: this.model } : {}), ...(this.effort ? { effort: this.effort } : {}),
408
+ ...speedOptions, ...goalPolicy });
398
409
  this.assertGoalOwner(run);
399
410
  if (run.controlling)
400
411
  return;
@@ -860,15 +871,22 @@ class CodexAppServerExecutor {
860
871
  }
861
872
  async listModels() {
862
873
  await this.refreshModelCatalogAfterCommandUpgrade();
874
+ return this.readModelCatalog();
875
+ }
876
+ async readModelCatalog() {
863
877
  const models = [];
864
878
  let cursor = null;
865
879
  const currentModelId = this.reportedModel ?? this.model;
866
880
  do {
867
- const response = await this.client.request('model/list', {
881
+ const owner = this.goalRun;
882
+ const params = {
868
883
  cursor,
869
884
  limit: 100,
870
885
  includeHidden: false,
871
- });
886
+ };
887
+ const response = await (owner ? this.goalRequest('model/list', params) : this.client.request('model/list', params));
888
+ if (owner)
889
+ this.assertGoalOwner(owner);
872
890
  for (const model of Array.isArray(response?.data) ? response.data : []) {
873
891
  if (typeof model?.id !== 'string')
874
892
  continue;
@@ -885,6 +903,11 @@ class CodexAppServerExecutor {
885
903
  ? model.defaultReasoningEffort
886
904
  : undefined,
887
905
  inputModalities: Array.isArray(model.inputModalities) ? model.inputModalities : undefined,
906
+ ...(Array.isArray(model.serviceTiers) && model.serviceTiers.length <= 32
907
+ && model.serviceTiers.every((tier) => tier && this.validSpeedValue(tier.id) && this.validSpeedValue(tier.name)
908
+ && (tier.description === undefined || (typeof tier.description === 'string' && tier.description.length <= 4096)))
909
+ ? { serviceTiers: model.serviceTiers.map((tier) => ({ id: tier.id, name: tier.name, description: tier.description })),
910
+ ...(model.defaultServiceTier === null || this.validSpeedValue(model.defaultServiceTier) ? { defaultServiceTier: model.defaultServiceTier } : {}) } : {}),
888
911
  });
889
912
  }
890
913
  cursor = typeof response?.nextCursor === 'string' ? response.nextCursor : null;
@@ -937,6 +960,10 @@ class CodexAppServerExecutor {
937
960
  if (!selected) {
938
961
  return { success: false, error: `Unknown Codex model: ${model}. Use /model to list available models.` };
939
962
  }
963
+ if (typeof this.speed === 'string' && (!selected.serviceTiers?.length
964
+ || (this.speed !== 'default' && !selected.serviceTiers.some(tier => tier.id === this.speed)))) {
965
+ return { success: false, error: 'The saved speed is incompatible with this model. Follow native config in the Speed section before changing models.' };
966
+ }
940
967
  if (this.effort && !selected.supportedReasoningEfforts?.includes(this.effort)) {
941
968
  return { success: false, error: 'The saved reasoning effort is incompatible with this model. Reset /effort auto before changing models.' };
942
969
  }
@@ -950,10 +977,157 @@ class CodexAppServerExecutor {
950
977
  }
951
978
  }
952
979
  clearModel() {
980
+ if (typeof this.speed === 'string')
981
+ throw new Error('Follow native config in the Speed section before clearing the model override.');
953
982
  this.model = undefined;
954
983
  this.reportedModel = undefined;
955
984
  this.reportedEffort = undefined;
956
985
  }
986
+ validSpeedValue(value) {
987
+ return typeof value === 'string' && value.length > 0 && value.length <= 512 && !/[\x00-\x1f\x7f]/.test(value);
988
+ }
989
+ async listSpeeds(models) {
990
+ const catalog = models ?? await this.listModels();
991
+ const recovery = this.speed !== undefined ? { choices: [], current: this.speed ?? undefined } : undefined;
992
+ // Do not add config RPCs to legacy catalogs or to models with no tier choices.
993
+ if (!catalog.some(model => model.serviceTiers?.length))
994
+ return recovery;
995
+ let id = this.reportedModel ?? this.model;
996
+ if (!id) {
997
+ try {
998
+ id = (await this.readNativeSpeedConfig()).model;
999
+ }
1000
+ catch (error) {
1001
+ // A failed native query must not turn a catalog default into an offer of
1002
+ // paid speed. A saved override can still be cleared without discovery.
1003
+ if (recovery)
1004
+ return recovery;
1005
+ throw error;
1006
+ }
1007
+ }
1008
+ const selected = id ? catalog.find(model => model.id === id) : catalog.find(model => model.isDefault);
1009
+ if (!selected?.serviceTiers?.length)
1010
+ return recovery;
1011
+ const choices = [{ value: 'default', displayName: 'Standard', description: 'Use standard processing.' },
1012
+ ...selected.serviceTiers.filter(tier => tier.id !== 'default').map(tier => ({ value: tier.id, displayName: tier.name, description: tier.description }))];
1013
+ return { choices, current: this.speed ?? undefined, default: selected.defaultServiceTier };
1014
+ }
1015
+ async assertReportedSpeed(speed) {
1016
+ if (!this.reportedModel)
1017
+ return;
1018
+ const owner = this.goalRun;
1019
+ const catalog = await (owner ? this.goalDeadline(this.readModelCatalog()) : this.readModelCatalog());
1020
+ if (owner)
1021
+ this.assertGoalOwner(owner);
1022
+ const selected = catalog.find(model => model.id === this.reportedModel);
1023
+ if (!selected?.serviceTiers?.length || (speed !== 'default' && !selected.serviceTiers.some(tier => tier.id === speed))) {
1024
+ throw new Error('This speed is unavailable for the model reported by Codex. Follow native config in /model before starting work.');
1025
+ }
1026
+ }
1027
+ async speedOptions(speed = this.speed) {
1028
+ if (speed === undefined)
1029
+ return {};
1030
+ if (speed !== null)
1031
+ return { serviceTier: speed };
1032
+ // Avoid the public upgrade check while preparing a turn: replacing the
1033
+ // transport here would discard the native thread just loaded by ensureThread.
1034
+ const catalog = await this.readModelCatalog();
1035
+ if (!catalog.some(model => model.serviceTiers !== undefined)) {
1036
+ if (this.codexThreadId && !(this.threadReady && this.legacyFollowReady)) {
1037
+ throw new Error('This Codex version cannot safely clear the speed of a saved conversation. Upgrade Codex or use /clear before resuming.');
1038
+ }
1039
+ // Old protocols must never receive unsupported serviceTier keys. A fresh
1040
+ // thread can safely use native startup configuration without an override.
1041
+ return {};
1042
+ }
1043
+ const config = await this.readNativeSpeedConfig();
1044
+ const id = this.reportedModel ?? this.model ?? config.model;
1045
+ const selected = id ? catalog.find(model => model.id === id) : catalog.find(model => model.isDefault);
1046
+ if (config.tier === 'fast' || config.tier === 'priority') {
1047
+ const fast = selected?.serviceTiers?.find(tier => tier.id === 'priority')
1048
+ ?? selected?.serviceTiers?.find(tier => tier.id === 'fast');
1049
+ return { serviceTier: config.fastMode && fast ? fast.id : null };
1050
+ }
1051
+ if (config.tier !== null && config.tier !== 'default' && config.tier !== 'flex'
1052
+ && !selected?.serviceTiers?.some(tier => tier.id === config.tier)) {
1053
+ throw new Error('Codex configured speed is unavailable for the selected model. Check native configuration before resuming.');
1054
+ }
1055
+ return { serviceTier: config.tier };
1056
+ }
1057
+ async readNativeSpeedConfig() {
1058
+ const owner = this.goalRun;
1059
+ const params = { includeLayers: false, cwd: this.currentWorkingDirectory };
1060
+ const response = await (owner ? this.goalRequest('config/read', params) : this.client.request('config/read', params));
1061
+ if (owner)
1062
+ this.assertGoalOwner(owner);
1063
+ if (!response?.config || typeof response.config !== 'object')
1064
+ throw new Error('Codex did not provide its native speed configuration.');
1065
+ const native = response.config.service_tier;
1066
+ if (native !== undefined && native !== null && !this.validSpeedValue(native))
1067
+ throw new Error('Codex returned an invalid native speed setting.');
1068
+ const model = response.config.model;
1069
+ if (model !== undefined && model !== null && !this.validSpeedValue(model))
1070
+ throw new Error('Codex returned an invalid configured model.');
1071
+ const features = response.config.features;
1072
+ if (features !== undefined && (features === null || typeof features !== 'object' || Array.isArray(features)))
1073
+ throw new Error('Codex returned invalid native speed features.');
1074
+ const fastMode = features?.fast_mode;
1075
+ if (fastMode !== undefined && typeof fastMode !== 'boolean')
1076
+ throw new Error('Codex returned an invalid native Fast mode setting.');
1077
+ return { model: model ?? undefined, tier: native ?? null, fastMode: fastMode !== false };
1078
+ }
1079
+ async setSpeed(speed) {
1080
+ try {
1081
+ const cwd = this.currentWorkingDirectory, threadId = this.codexThreadId;
1082
+ const assertCurrent = () => {
1083
+ if (this.isBusy() || this.destroyed || cwd !== this.currentWorkingDirectory || threadId !== this.codexThreadId)
1084
+ throw new Error('The Codex thread changed during speed selection.');
1085
+ };
1086
+ if (this.isBusy() || this.destroyed)
1087
+ throw new Error('The Codex thread must be idle to change speed.');
1088
+ if (speed === undefined) {
1089
+ // Reset is recovery, not another selection. Never load a saved thread
1090
+ // through its obsolete tier, nor resume suspended native goals here.
1091
+ this.threadReady = false;
1092
+ this.legacyFollowReady = false;
1093
+ this.threadLoads++;
1094
+ try {
1095
+ await this.client.stop();
1096
+ await this.client.waitForExit?.();
1097
+ }
1098
+ finally {
1099
+ this.threadLoads--;
1100
+ }
1101
+ assertCurrent();
1102
+ this.speed = null;
1103
+ return { success: true, output: 'Speed follows native configuration on the next safe resume. Older Codex versions may require an upgrade or /clear.' };
1104
+ }
1105
+ const choices = await this.listSpeeds();
1106
+ assertCurrent();
1107
+ if (!choices || !choices.choices.some(choice => choice.value === speed)) {
1108
+ throw new Error('This speed is unavailable for the current Codex model. Refresh /model.');
1109
+ }
1110
+ if (this.isBusy() || this.destroyed)
1111
+ throw new Error('The Codex thread changed during speed selection.');
1112
+ if (this.codexThreadId && !(this.goalManaged && this.goalNeedsResume)) {
1113
+ await this.ensureThread();
1114
+ assertCurrent();
1115
+ // Restored conversations can report a different model than the preview.
1116
+ await this.assertReportedSpeed(speed);
1117
+ assertCurrent();
1118
+ // Explicit selections may update a live thread. Follow never loads it.
1119
+ const { serviceTier } = await this.speedOptions(speed);
1120
+ assertCurrent();
1121
+ await this.client.request('thread/settings/update', { threadId: this.codexThreadId, serviceTier });
1122
+ assertCurrent();
1123
+ }
1124
+ this.speed = speed;
1125
+ return { success: true, output: 'Speed preference applied.' };
1126
+ }
1127
+ catch (error) {
1128
+ return { success: false, error: this.errorMessage(error) };
1129
+ }
1130
+ }
957
1131
  async listEfforts() {
958
1132
  const models = await this.listModels();
959
1133
  const currentModelId = this.reportedModel ?? this.model;
@@ -1081,14 +1255,28 @@ class CodexAppServerExecutor {
1081
1255
  }
1082
1256
  if (this.threadReady && this.client.isRunning())
1083
1257
  return;
1258
+ this.threadReady = false;
1259
+ this.legacyFollowReady = false;
1084
1260
  const goalOwner = this.goalRun;
1085
1261
  this.reportedModel = undefined;
1086
1262
  this.reportedEffort = undefined;
1087
1263
  await this.client.start();
1264
+ if (goalOwner)
1265
+ this.assertGoalOwner(goalOwner);
1266
+ if (typeof this.speed === 'string') {
1267
+ const available = await (goalOwner ? this.goalDeadline(this.listSpeeds()) : this.listSpeeds());
1268
+ if (goalOwner)
1269
+ this.assertGoalOwner(goalOwner);
1270
+ if (!available?.choices.some(choice => choice.value === this.speed)) {
1271
+ throw new Error('The saved speed is unavailable for this Codex model. Follow native config in /model before starting work.');
1272
+ }
1273
+ }
1274
+ const speedOptions = await this.speedOptions();
1088
1275
  if (goalOwner)
1089
1276
  this.assertGoalOwner(goalOwner);
1090
1277
  const common = {
1091
1278
  ...(this.model ? { model: this.model } : {}),
1279
+ ...speedOptions,
1092
1280
  cwd: this.currentWorkingDirectory,
1093
1281
  ...(this.autoApprove ? {
1094
1282
  approvalPolicy: 'never',
@@ -1144,7 +1332,12 @@ class CodexAppServerExecutor {
1144
1332
  throw new Error('Codex app-server returned no thread ID');
1145
1333
  this.captureReportedSettings(response);
1146
1334
  this.setThreadId(id);
1335
+ this.legacyFollowReady = this.speed === null && !Object.prototype.hasOwnProperty.call(common, 'serviceTier');
1147
1336
  }
1337
+ if (typeof this.speed === 'string')
1338
+ await this.assertReportedSpeed(this.speed);
1339
+ if (goalOwner)
1340
+ this.assertGoalOwner(goalOwner);
1148
1341
  this.threadReady = true;
1149
1342
  }
1150
1343
  handleMessage(message) {