@autohq/cli 0.1.123 → 0.1.125

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.
@@ -21623,8 +21623,11 @@ var SessionIdentitySchema = external_exports.object({
21623
21623
  }).strict().refine((identity) => Object.keys(identity).length > 0, {
21624
21624
  message: "Session identity requires at least one field"
21625
21625
  });
21626
- var SessionSpecSchema = external_exports.object({
21627
- profile: ResourceNameSchema,
21626
+ var SessionSpecFieldsSchema = external_exports.object({
21627
+ profile: ResourceNameSchema.optional(),
21628
+ harness: external_exports.enum(PROFILE_HARNESSES).optional(),
21629
+ systemPrompt: external_exports.string().trim().min(1).max(1e5).optional(),
21630
+ environment: ResourceNameSchema.optional(),
21628
21631
  identity: SessionIdentitySchema.optional(),
21629
21632
  initialPrompt: external_exports.string().trim().min(1).max(2e4).optional(),
21630
21633
  env: SecretEnvSchema.default({}),
@@ -21633,9 +21636,31 @@ var SessionSpecSchema = external_exports.object({
21633
21636
  workingDirectory: external_exports.string().trim().min(1).optional(),
21634
21637
  tools: SessionToolsSchema.default({})
21635
21638
  });
21636
- var SessionApplySpecSchema = SessionSpecSchema.extend({
21639
+ function validateSessionRunnableConfig(spec, context) {
21640
+ if (spec.profile) {
21641
+ return;
21642
+ }
21643
+ if (!spec.harness) {
21644
+ context.addIssue({
21645
+ code: external_exports.ZodIssueCode.custom,
21646
+ path: ["harness"],
21647
+ message: "Session requires harness when profile is omitted"
21648
+ });
21649
+ }
21650
+ if (!spec.environment) {
21651
+ context.addIssue({
21652
+ code: external_exports.ZodIssueCode.custom,
21653
+ path: ["environment"],
21654
+ message: "Session requires environment when profile is omitted"
21655
+ });
21656
+ }
21657
+ }
21658
+ var SessionSpecSchema = SessionSpecFieldsSchema.superRefine(
21659
+ validateSessionRunnableConfig
21660
+ );
21661
+ var SessionApplySpecSchema = SessionSpecFieldsSchema.extend({
21637
21662
  triggers: SessionApplyTriggersSchema.default([])
21638
- });
21663
+ }).superRefine(validateSessionRunnableConfig);
21639
21664
  var SessionStatusSchema = external_exports.object({
21640
21665
  runCount: external_exports.number().int().nonnegative().default(0)
21641
21666
  }).default({ runCount: 0 });
@@ -26269,7 +26294,7 @@ Object.assign(lookup, {
26269
26294
  // package.json
26270
26295
  var package_default = {
26271
26296
  name: "@autohq/cli",
26272
- version: "0.1.123",
26297
+ version: "0.1.125",
26273
26298
  license: "SEE LICENSE IN README.md",
26274
26299
  publishConfig: {
26275
26300
  access: "public"
package/dist/index.js CHANGED
@@ -18116,6 +18116,25 @@ function isAvatarAssetPathShapeValid(asset) {
18116
18116
  const lower = normalized.toLowerCase();
18117
18117
  return AVATAR_ASSET_EXTENSIONS.some((ext) => lower.endsWith(ext));
18118
18118
  }
18119
+ function validateSessionRunnableConfig(spec, context) {
18120
+ if (spec.profile) {
18121
+ return;
18122
+ }
18123
+ if (!spec.harness) {
18124
+ context.addIssue({
18125
+ code: external_exports.ZodIssueCode.custom,
18126
+ path: ["harness"],
18127
+ message: "Session requires harness when profile is omitted"
18128
+ });
18129
+ }
18130
+ if (!spec.environment) {
18131
+ context.addIssue({
18132
+ code: external_exports.ZodIssueCode.custom,
18133
+ path: ["environment"],
18134
+ message: "Session requires environment when profile is omitted"
18135
+ });
18136
+ }
18137
+ }
18119
18138
  function validateTriggerChecks(trigger, context, eventKeys) {
18120
18139
  const checks = trigger.checks ?? [];
18121
18140
  if (checks.length === 0) {
@@ -18239,7 +18258,7 @@ function isChatMessageEvent(trigger) {
18239
18258
  function hasFilterValue(trigger, path2, expected) {
18240
18259
  return trigger.where?.[path2] === expected;
18241
18260
  }
18242
- var RESOURCE_KIND_SESSION, TriggerFilterScalarSchema, TriggerFilterPathSchema, TriggerFilterClauseSchema, TriggerFilterSchema, SessionTriggerCheckTimeoutSchema, TriggerEventSchema, TriggerEventsSchema, SessionTriggerSharedFields, SessionTriggerEventSourceFields, SessionTriggerBaseSchema, SessionTriggerDefinitionBaseSchema, SessionTriggerSchema, SessionApplyTriggerSchema, SessionHeartbeatTriggerBaseSchema, SessionHeartbeatTriggerSchema, SessionApplyHeartbeatTriggerSchema, SessionTriggerDefinitionSchema, SessionApplyTriggerDefinitionSchema, SessionTriggersSchema, SessionApplyTriggersSchema, AVATAR_ASSET_EXTENSIONS, MAX_AVATAR_ASSET_BYTES, MIN_AVATAR_ASSET_DIMENSION_PX, MAX_AVATAR_ASSET_DIMENSION_PX, PNG_SIGNATURE, SESSION_IDENTITY_DESCRIPTION_MAX_LENGTH, SHA256_HEX_PATTERN, SessionIdentitySchema, SessionSpecSchema, SessionApplySpecSchema, SessionStatusSchema, SessionResourceSchema, SessionApplyRequestSchema, SessionApplyTriggerReceiptSchema, SessionApplyResponseSchema, SESSION_TELEGRAM_IDENTITY_STATUSES, SessionTelegramIdentityStatusSchema, SessionPresenceIdentitySchema, SessionPresenceResponseSchema, SessionPresenceConnectRequestSchema, SessionPresenceConnectPendingSchema, SessionPresenceConnectResponseSchema, SessionPresenceIconRequestSchema, SessionPresenceIconResponseSchema, SessionPresenceCompleteResponseSchema;
18261
+ var RESOURCE_KIND_SESSION, TriggerFilterScalarSchema, TriggerFilterPathSchema, TriggerFilterClauseSchema, TriggerFilterSchema, SessionTriggerCheckTimeoutSchema, TriggerEventSchema, TriggerEventsSchema, SessionTriggerSharedFields, SessionTriggerEventSourceFields, SessionTriggerBaseSchema, SessionTriggerDefinitionBaseSchema, SessionTriggerSchema, SessionApplyTriggerSchema, SessionHeartbeatTriggerBaseSchema, SessionHeartbeatTriggerSchema, SessionApplyHeartbeatTriggerSchema, SessionTriggerDefinitionSchema, SessionApplyTriggerDefinitionSchema, SessionTriggersSchema, SessionApplyTriggersSchema, AVATAR_ASSET_EXTENSIONS, MAX_AVATAR_ASSET_BYTES, MIN_AVATAR_ASSET_DIMENSION_PX, MAX_AVATAR_ASSET_DIMENSION_PX, PNG_SIGNATURE, SESSION_IDENTITY_DESCRIPTION_MAX_LENGTH, SHA256_HEX_PATTERN, SessionIdentitySchema, SessionSpecFieldsSchema, SessionSpecSchema, SessionApplySpecSchema, SessionStatusSchema, SessionResourceSchema, SessionApplyRequestSchema, SessionApplyTriggerReceiptSchema, SessionApplyResponseSchema, SESSION_TELEGRAM_IDENTITY_STATUSES, SessionTelegramIdentityStatusSchema, SessionPresenceIdentitySchema, SessionPresenceResponseSchema, SessionPresenceConnectRequestSchema, SessionPresenceConnectPendingSchema, SessionPresenceConnectResponseSchema, SessionPresenceIconRequestSchema, SessionPresenceIconResponseSchema, SessionPresenceCompleteResponseSchema;
18243
18262
  var init_sessions = __esm({
18244
18263
  "../../packages/schemas/src/sessions.ts"() {
18245
18264
  "use strict";
@@ -18247,6 +18266,7 @@ var init_sessions = __esm({
18247
18266
  init_connections();
18248
18267
  init_mounts();
18249
18268
  init_primitives();
18269
+ init_profiles2();
18250
18270
  init_resources();
18251
18271
  init_secrets();
18252
18272
  init_tools();
@@ -18442,8 +18462,11 @@ var init_sessions = __esm({
18442
18462
  }).strict().refine((identity2) => Object.keys(identity2).length > 0, {
18443
18463
  message: "Session identity requires at least one field"
18444
18464
  });
18445
- SessionSpecSchema = external_exports.object({
18446
- profile: ResourceNameSchema,
18465
+ SessionSpecFieldsSchema = external_exports.object({
18466
+ profile: ResourceNameSchema.optional(),
18467
+ harness: external_exports.enum(PROFILE_HARNESSES).optional(),
18468
+ systemPrompt: external_exports.string().trim().min(1).max(1e5).optional(),
18469
+ environment: ResourceNameSchema.optional(),
18447
18470
  identity: SessionIdentitySchema.optional(),
18448
18471
  initialPrompt: external_exports.string().trim().min(1).max(2e4).optional(),
18449
18472
  env: SecretEnvSchema.default({}),
@@ -18452,9 +18475,12 @@ var init_sessions = __esm({
18452
18475
  workingDirectory: external_exports.string().trim().min(1).optional(),
18453
18476
  tools: SessionToolsSchema.default({})
18454
18477
  });
18455
- SessionApplySpecSchema = SessionSpecSchema.extend({
18478
+ SessionSpecSchema = SessionSpecFieldsSchema.superRefine(
18479
+ validateSessionRunnableConfig
18480
+ );
18481
+ SessionApplySpecSchema = SessionSpecFieldsSchema.extend({
18456
18482
  triggers: SessionApplyTriggersSchema.default([])
18457
- });
18483
+ }).superRefine(validateSessionRunnableConfig);
18458
18484
  SessionStatusSchema = external_exports.object({
18459
18485
  runCount: external_exports.number().int().nonnegative().default(0)
18460
18486
  }).default({ runCount: 0 });
@@ -18783,7 +18809,12 @@ var init_run_diagnostics = __esm({
18783
18809
  });
18784
18810
 
18785
18811
  // ../../packages/schemas/src/session-runs.ts
18786
- var SESSION_RUN_STATUSES, SESSION_RUN_DISPLAY_TITLE_MAX_LENGTH, SessionRunStatusSchema, SessionRunDisplayTitleSchema, SESSION_RUN_CHECK_STATUSES, SESSION_RUN_CHECK_CONCLUSIONS, SESSION_RUN_CHECK_TIMEOUT_PHASES, SessionRunCheckStatusSchema, SessionRunCheckConclusionSchema, SessionRunCheckTimeoutPhaseSchema, ManualSessionRunRequestSchema, SessionRunArchiveRequestSchema, SessionRunsArchiveRequestSchema, SessionRunRecordSchema, SessionRunsArchiveResponseSchema;
18812
+ function isSessionRunTerminalStatus(status) {
18813
+ return SESSION_RUN_TERMINAL_STATUSES.some(
18814
+ (terminalStatus) => terminalStatus === status
18815
+ );
18816
+ }
18817
+ var SESSION_RUN_STATUSES, SESSION_RUN_TERMINAL_STATUSES, SESSION_RUN_DISPLAY_TITLE_MAX_LENGTH, SessionRunStatusSchema, SessionRunDisplayTitleSchema, SESSION_RUN_CHECK_STATUSES, SESSION_RUN_CHECK_CONCLUSIONS, SESSION_RUN_CHECK_TIMEOUT_PHASES, SessionRunCheckStatusSchema, SessionRunCheckConclusionSchema, SessionRunCheckTimeoutPhaseSchema, ManualSessionRunRequestSchema, SessionRunArchiveRequestSchema, SessionRunsArchiveRequestSchema, SessionRunRecordSchema, SessionRunsArchiveResponseSchema;
18787
18818
  var init_session_runs = __esm({
18788
18819
  "../../packages/schemas/src/session-runs.ts"() {
18789
18820
  "use strict";
@@ -18802,6 +18833,7 @@ var init_session_runs = __esm({
18802
18833
  "failed",
18803
18834
  "stopped"
18804
18835
  ];
18836
+ SESSION_RUN_TERMINAL_STATUSES = ["failed", "stopped"];
18805
18837
  SESSION_RUN_DISPLAY_TITLE_MAX_LENGTH = 64;
18806
18838
  SessionRunStatusSchema = external_exports.enum(SESSION_RUN_STATUSES);
18807
18839
  SessionRunDisplayTitleSchema = external_exports.string().trim().max(SESSION_RUN_DISPLAY_TITLE_MAX_LENGTH);
@@ -21231,7 +21263,7 @@ var init_package = __esm({
21231
21263
  "package.json"() {
21232
21264
  package_default = {
21233
21265
  name: "@autohq/cli",
21234
- version: "0.1.123",
21266
+ version: "0.1.125",
21235
21267
  license: "SEE LICENSE IN README.md",
21236
21268
  publishConfig: {
21237
21269
  access: "public"
@@ -24907,6 +24939,39 @@ function useUnarchiveRuns(apiUrl) {
24907
24939
  onSuccess: (result) => invalidateRunsQueries(queryClient, apiUrl, result.runs)
24908
24940
  });
24909
24941
  }
24942
+ function useStopRuns(apiUrl) {
24943
+ const client = useApiClient();
24944
+ const queryClient = useQueryClient();
24945
+ return useMutation({
24946
+ mutationFn: (runIds) => stopRunsBatch(
24947
+ (runId) => client.stopRun(runId, { apiBaseUrl: apiUrl }),
24948
+ runIds
24949
+ ),
24950
+ // stopRun returns a command receipt, not run records, so invalidate the
24951
+ // run-list query families directly to pick up the new statuses.
24952
+ onSuccess: () => invalidateRunListQueries(queryClient, apiUrl)
24953
+ });
24954
+ }
24955
+ async function stopRunsBatch(stopRun, runIds) {
24956
+ const outcomes = await Promise.all(
24957
+ runIds.map(async (runId) => {
24958
+ try {
24959
+ await stopRun(runId);
24960
+ return { runId, ok: true, message: "" };
24961
+ } catch (error51) {
24962
+ return {
24963
+ runId,
24964
+ ok: false,
24965
+ message: error51 instanceof Error ? error51.message : String(error51)
24966
+ };
24967
+ }
24968
+ })
24969
+ );
24970
+ return {
24971
+ stopped: outcomes.filter((o) => o.ok).map((o) => o.runId),
24972
+ failed: outcomes.filter((o) => !o.ok).map((o) => ({ runId: o.runId, message: o.message }))
24973
+ };
24974
+ }
24910
24975
  function sessionRunsQueryOptions(client, sessionName, apiUrl, includeArchived = false) {
24911
24976
  return queryOptions({
24912
24977
  queryKey: queryKeys.sessionRuns(sessionName ?? "", apiUrl, includeArchived),
@@ -25031,7 +25096,7 @@ function connectionProvidersQueryOptions(client, apiUrl, enabled = true) {
25031
25096
  }
25032
25097
  function sortSessions(list) {
25033
25098
  return list.slice().sort(
25034
- (a, b) => a.spec.profile.localeCompare(b.spec.profile) || a.metadata.name.localeCompare(b.metadata.name)
25099
+ (a, b) => (a.spec.profile ?? "").localeCompare(b.spec.profile ?? "") || a.metadata.name.localeCompare(b.metadata.name)
25035
25100
  );
25036
25101
  }
25037
25102
  function sortByName(list) {
@@ -25047,6 +25112,10 @@ function invalidateRunsQueries(queryClient, apiUrl, runs) {
25047
25112
  });
25048
25113
  }
25049
25114
  }
25115
+ function invalidateRunListQueries(queryClient, apiUrl) {
25116
+ void queryClient.invalidateQueries({ queryKey: ["runs", apiUrl] });
25117
+ void queryClient.invalidateQueries({ queryKey: ["session-runs"] });
25118
+ }
25050
25119
  var TUI_RUN_LIST_LIMIT, queryKeys, RUNS_REFETCH_INTERVAL_MS;
25051
25120
  var init_queries = __esm({
25052
25121
  "src/tui/hooks/queries.ts"() {
@@ -25579,6 +25648,9 @@ function HomeView({ apiUrl, notice, returnToSession }) {
25579
25648
  );
25580
25649
  const [pendingArchiveRunKey, setPendingArchiveRunKey] = useState3(null);
25581
25650
  const [pendingUnarchiveRunKey, setPendingUnarchiveRunKey] = useState3(null);
25651
+ const [pendingStopRunKey, setPendingStopRunKey] = useState3(
25652
+ null
25653
+ );
25582
25654
  const [runNotice, setRunNotice] = useState3(null);
25583
25655
  const [connectionIndex, setConnectionIndex] = useState3(0);
25584
25656
  const [connectionProviderIndex, setConnectionProviderIndex] = useState3(0);
@@ -25644,6 +25716,7 @@ function HomeView({ apiUrl, notice, returnToSession }) {
25644
25716
  const triggerRun = useTriggerRun(apiUrl);
25645
25717
  const archiveRuns = useArchiveRuns(apiUrl);
25646
25718
  const unarchiveRuns = useUnarchiveRuns(apiUrl);
25719
+ const stopRuns = useStopRuns(apiUrl);
25647
25720
  const [connectionNotice, setConnectionNotice] = useState3(null);
25648
25721
  const [serviceAccountNotice, setServiceAccountNotice] = useState3(null);
25649
25722
  const [pendingRemoveConnectionKey, setPendingRemoveConnectionKey] = useState3(null);
@@ -25792,14 +25865,14 @@ function HomeView({ apiUrl, notice, returnToSession }) {
25792
25865
  });
25793
25866
  }, [visibleRunIdKey]);
25794
25867
  useEffect3(() => {
25795
- if (!selectedSession) return;
25868
+ if (!selectedSession?.spec.profile) return;
25796
25869
  const index = profiles.findIndex(
25797
25870
  (profile) => profile.metadata.name === selectedSession.spec.profile
25798
25871
  );
25799
25872
  if (index >= 0) setProfileIndex(index);
25800
25873
  }, [profiles, selectedSession]);
25801
25874
  useEffect3(() => {
25802
- const environmentName = selectedProfile?.spec.environment ?? profiles.find(
25875
+ const environmentName = selectedProfile?.spec.environment ?? selectedSession?.spec.environment ?? profiles.find(
25803
25876
  (profile) => profile.metadata.name === selectedSession?.spec.profile
25804
25877
  )?.spec.environment;
25805
25878
  if (!environmentName) return;
@@ -25841,8 +25914,10 @@ function HomeView({ apiUrl, notice, returnToSession }) {
25841
25914
  const toggleSelectedRun = useCallback2(() => {
25842
25915
  setPendingArchiveRunKey(null);
25843
25916
  setPendingUnarchiveRunKey(null);
25917
+ setPendingStopRunKey(null);
25844
25918
  archiveRuns.reset();
25845
25919
  unarchiveRuns.reset();
25920
+ stopRuns.reset();
25846
25921
  if (!selectedRun) {
25847
25922
  setRunNotice("Select a run before marking it.");
25848
25923
  return;
@@ -25860,11 +25935,13 @@ function HomeView({ apiUrl, notice, returnToSession }) {
25860
25935
  setRunNotice(
25861
25936
  wasSelected ? `Unmarked run ${shortRunId2(selectedRun.id)}.` : `Marked run ${shortRunId2(selectedRun.id)}.`
25862
25937
  );
25863
- }, [archiveRuns, selectedRun, selectedRunIds, unarchiveRuns]);
25938
+ }, [archiveRuns, selectedRun, selectedRunIds, stopRuns, unarchiveRuns]);
25864
25939
  const archiveSelectedRun = useCallback2(() => {
25865
25940
  archiveRuns.reset();
25866
25941
  unarchiveRuns.reset();
25942
+ stopRuns.reset();
25867
25943
  setPendingUnarchiveRunKey(null);
25944
+ setPendingStopRunKey(null);
25868
25945
  const runIds = runIdsForArchiveAction({
25869
25946
  markedRunIds,
25870
25947
  selectedRun
@@ -25894,12 +25971,15 @@ function HomeView({ apiUrl, notice, returnToSession }) {
25894
25971
  markedRunIds,
25895
25972
  pendingArchiveRunKey,
25896
25973
  selectedRun,
25974
+ stopRuns,
25897
25975
  unarchiveRuns
25898
25976
  ]);
25899
25977
  const unarchiveSelectedRun = useCallback2(() => {
25900
25978
  archiveRuns.reset();
25901
25979
  unarchiveRuns.reset();
25980
+ stopRuns.reset();
25902
25981
  setPendingArchiveRunKey(null);
25982
+ setPendingStopRunKey(null);
25903
25983
  const runIds = runIdsForArchiveAction({
25904
25984
  markedRunIds,
25905
25985
  selectedRun
@@ -25929,8 +26009,59 @@ function HomeView({ apiUrl, notice, returnToSession }) {
25929
26009
  markedRunIds,
25930
26010
  pendingUnarchiveRunKey,
25931
26011
  selectedRun,
26012
+ stopRuns,
25932
26013
  unarchiveRuns
25933
26014
  ]);
26015
+ const stopSelectedRuns = useCallback2(() => {
26016
+ stopRuns.reset();
26017
+ archiveRuns.reset();
26018
+ unarchiveRuns.reset();
26019
+ setPendingArchiveRunKey(null);
26020
+ setPendingUnarchiveRunKey(null);
26021
+ const runIds = runIdsForArchiveAction({ markedRunIds, selectedRun });
26022
+ if (runIds.length === 0) {
26023
+ setPendingStopRunKey(null);
26024
+ setRunNotice("Select a run before stopping.");
26025
+ return;
26026
+ }
26027
+ const runsById = new Map(visibleRuns.map((run) => [run.id, run]));
26028
+ const { stoppableRunIds, skippedRunIds } = partitionRunsForStop(
26029
+ runIds,
26030
+ runsById
26031
+ );
26032
+ if (stoppableRunIds.length === 0) {
26033
+ setPendingStopRunKey(null);
26034
+ setRunNotice(
26035
+ `Nothing to stop \u2014 ${pluralizeRunCount(skippedRunIds.length)} already stopped or failed.`
26036
+ );
26037
+ return;
26038
+ }
26039
+ const actionKey = runArchiveActionKey(stoppableRunIds);
26040
+ if (pendingStopRunKey !== actionKey) {
26041
+ setPendingStopRunKey(actionKey);
26042
+ const skipNote = skippedRunIds.length > 0 ? ` (skipping ${pluralizeRunCount(skippedRunIds.length)} already stopped or failed)` : "";
26043
+ setRunNotice(
26044
+ `Press s again to stop ${stopTargetLabel(stoppableRunIds, markedRunIds.length > 0)}${skipNote}.`
26045
+ );
26046
+ return;
26047
+ }
26048
+ setPendingStopRunKey(null);
26049
+ setRunNotice(null);
26050
+ stopRuns.mutate(stoppableRunIds, {
26051
+ onSuccess: (result) => {
26052
+ setSelectedRunIds(/* @__PURE__ */ new Set());
26053
+ setRunNotice(stopResultNotice(result, skippedRunIds.length));
26054
+ }
26055
+ });
26056
+ }, [
26057
+ archiveRuns,
26058
+ markedRunIds,
26059
+ pendingStopRunKey,
26060
+ selectedRun,
26061
+ stopRuns,
26062
+ unarchiveRuns,
26063
+ visibleRuns
26064
+ ]);
25934
26065
  const projectSelectionRequired = /No active (organization|project)/i.test(authErrorMessage ?? "") && projects.length > 0;
25935
26066
  useEffect3(() => {
25936
26067
  if (projectSelectionRequired) {
@@ -26091,6 +26222,7 @@ function HomeView({ apiUrl, notice, returnToSession }) {
26091
26222
  setSelectedRunIds(/* @__PURE__ */ new Set());
26092
26223
  setPendingArchiveRunKey(null);
26093
26224
  setPendingUnarchiveRunKey(null);
26225
+ setPendingStopRunKey(null);
26094
26226
  setRunNotice(null);
26095
26227
  triggerRun.reset();
26096
26228
  return;
@@ -26102,6 +26234,7 @@ function HomeView({ apiUrl, notice, returnToSession }) {
26102
26234
  setSelectedRunIds(/* @__PURE__ */ new Set());
26103
26235
  setPendingArchiveRunKey(null);
26104
26236
  setPendingUnarchiveRunKey(null);
26237
+ setPendingStopRunKey(null);
26105
26238
  setRunNotice(null);
26106
26239
  setSection("runs");
26107
26240
  triggerRun.reset();
@@ -26125,6 +26258,7 @@ function HomeView({ apiUrl, notice, returnToSession }) {
26125
26258
  setSelectedRunIds(/* @__PURE__ */ new Set());
26126
26259
  setPendingArchiveRunKey(null);
26127
26260
  setPendingUnarchiveRunKey(null);
26261
+ setPendingStopRunKey(null);
26128
26262
  setRunNotice(null);
26129
26263
  setShowArchivedRuns(false);
26130
26264
  }
@@ -26208,6 +26342,7 @@ function HomeView({ apiUrl, notice, returnToSession }) {
26208
26342
  setSelectedRunIds(/* @__PURE__ */ new Set());
26209
26343
  setPendingArchiveRunKey(null);
26210
26344
  setPendingUnarchiveRunKey(null);
26345
+ setPendingStopRunKey(null);
26211
26346
  setRunNotice(null);
26212
26347
  setSection("runs");
26213
26348
  triggerRun.reset();
@@ -26226,9 +26361,11 @@ function HomeView({ apiUrl, notice, returnToSession }) {
26226
26361
  setSelectedRunIds(/* @__PURE__ */ new Set());
26227
26362
  setPendingArchiveRunKey(null);
26228
26363
  setPendingUnarchiveRunKey(null);
26364
+ setPendingStopRunKey(null);
26229
26365
  setRunNotice(null);
26230
26366
  archiveRuns.reset();
26231
26367
  unarchiveRuns.reset();
26368
+ stopRuns.reset();
26232
26369
  return;
26233
26370
  }
26234
26371
  if (input === " ") {
@@ -26243,6 +26380,10 @@ function HomeView({ apiUrl, notice, returnToSession }) {
26243
26380
  archiveSelectedRun();
26244
26381
  return;
26245
26382
  }
26383
+ if (input === "s" && !showArchivedRuns) {
26384
+ stopSelectedRuns();
26385
+ return;
26386
+ }
26246
26387
  if (input === "u" && showArchivedRuns) {
26247
26388
  unarchiveSelectedRun();
26248
26389
  return;
@@ -26250,12 +26391,14 @@ function HomeView({ apiUrl, notice, returnToSession }) {
26250
26391
  if (key.upArrow) {
26251
26392
  setPendingArchiveRunKey(null);
26252
26393
  setPendingUnarchiveRunKey(null);
26394
+ setPendingStopRunKey(null);
26253
26395
  setRunIndex((i) => Math.max(0, i - 1));
26254
26396
  return;
26255
26397
  }
26256
26398
  if (key.downArrow) {
26257
26399
  setPendingArchiveRunKey(null);
26258
26400
  setPendingUnarchiveRunKey(null);
26401
+ setPendingStopRunKey(null);
26259
26402
  setRunIndex((i) => clampListIndex(i + 1, visibleRuns.length));
26260
26403
  return;
26261
26404
  }
@@ -26616,8 +26759,8 @@ function HomeView({ apiUrl, notice, returnToSession }) {
26616
26759
  if (inspectedResource) {
26617
26760
  sectionTitle = `Inspect ${inspectedResource.kind}/${inspectedResource.name}`;
26618
26761
  }
26619
- const runError = errorMessage2(triggerRun.error) ?? errorMessage2(archiveRuns.error) ?? errorMessage2(unarchiveRuns.error);
26620
- const isRunMutationPending = triggerRun.isPending || archiveRuns.isPending || unarchiveRuns.isPending;
26762
+ const runError = errorMessage2(triggerRun.error) ?? errorMessage2(archiveRuns.error) ?? errorMessage2(unarchiveRuns.error) ?? errorMessage2(stopRuns.error);
26763
+ const isRunMutationPending = triggerRun.isPending || archiveRuns.isPending || unarchiveRuns.isPending || stopRuns.isPending;
26621
26764
  const isConnectionMutationPending = startConnection.isPending || allowConnection.isPending || removeConnection.isPending;
26622
26765
  const serviceAccountStatus = createServiceAccount2.error instanceof Error ? createServiceAccount2.error.message : rotateServiceAccount2.error instanceof Error ? rotateServiceAccount2.error.message : removeServiceAccount2.error instanceof Error ? removeServiceAccount2.error.message : serviceAccountNotice;
26623
26766
  const isServiceAccountMutationPending = createServiceAccount2.isPending || rotateServiceAccount2.isPending || removeServiceAccount2.isPending;
@@ -26639,7 +26782,11 @@ function HomeView({ apiUrl, notice, returnToSession }) {
26639
26782
  value: /* @__PURE__ */ jsx14(
26640
26783
  Spinner,
26641
26784
  {
26642
- label: triggerRun.isPending ? "starting\u2026" : archiveRuns.isPending ? "archiving\u2026" : "restoring\u2026"
26785
+ label: runMutationStatusLabel({
26786
+ starting: triggerRun.isPending,
26787
+ archiving: archiveRuns.isPending,
26788
+ stopping: stopRuns.isPending
26789
+ })
26643
26790
  }
26644
26791
  )
26645
26792
  }
@@ -26728,6 +26875,7 @@ function HomeView({ apiUrl, notice, returnToSession }) {
26728
26875
  },
26729
26876
  ...showArchivedRuns ? [{ k: "u", label: "Restore" }] : [
26730
26877
  { k: "a", label: "Archive" },
26878
+ { k: "s", label: "Stop" },
26731
26879
  ...scopedSession ? [{ k: "n", label: "New run" }] : []
26732
26880
  ],
26733
26881
  { k: "esc", label: "Back" },
@@ -26961,6 +27109,38 @@ function selectedRunIdsForVisibleRuns(runs, selectedRunIds) {
26961
27109
  function runIdsForArchiveAction(input) {
26962
27110
  return input.markedRunIds.length > 0 ? input.markedRunIds : input.selectedRun ? [input.selectedRun.id] : [];
26963
27111
  }
27112
+ function partitionRunsForStop(runIds, runsById) {
27113
+ const stoppableRunIds = [];
27114
+ const skippedRunIds = [];
27115
+ for (const runId of runIds) {
27116
+ const run = runsById.get(runId);
27117
+ if (run && isSessionRunTerminalStatus(run.status)) {
27118
+ skippedRunIds.push(runId);
27119
+ } else {
27120
+ stoppableRunIds.push(runId);
27121
+ }
27122
+ }
27123
+ return { stoppableRunIds, skippedRunIds };
27124
+ }
27125
+ function stopTargetLabel(runIds, bulk) {
27126
+ return bulk ? pluralizeRunCount(runIds.length) : `run ${shortRunId2(runIds[0] ?? "")}`;
27127
+ }
27128
+ function stopResultNotice(result, skippedCount) {
27129
+ const parts = [`Stopped ${pluralizeRunCount(result.stopped.length)}`];
27130
+ if (result.failed.length > 0) {
27131
+ parts.push(`failed to stop ${result.failed.length}`);
27132
+ }
27133
+ if (skippedCount > 0) {
27134
+ parts.push(`skipped ${skippedCount} already stopped or failed`);
27135
+ }
27136
+ return `${parts.join(", ")}.`;
27137
+ }
27138
+ function runMutationStatusLabel(pending) {
27139
+ if (pending.starting) return "starting\u2026";
27140
+ if (pending.archiving) return "archiving\u2026";
27141
+ if (pending.stopping) return "stopping\u2026";
27142
+ return "restoring\u2026";
27143
+ }
26964
27144
  function runArchiveActionKey(runIds) {
26965
27145
  return runIds.join("\0");
26966
27146
  }
@@ -27074,6 +27254,7 @@ var CONNECTION_REFRESH_INTERVAL_MS, CONNECTION_REFRESH_TIMEOUT_MS, DASHBOARD_NAV
27074
27254
  var init_HomeView = __esm({
27075
27255
  "src/tui/HomeView.tsx"() {
27076
27256
  "use strict";
27257
+ init_src();
27077
27258
  init_login();
27078
27259
  init_base_url();
27079
27260
  init_browser();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.123",
3
+ "version": "0.1.125",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"