@halcyonlabs/app 0.47.0-halcyon.101 → 0.47.0-halcyon.102

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -451,8 +451,8 @@ type ChangedMessage = z$1.infer<typeof changedMessageSchema>;
451
451
 
452
452
  declare const environmentStatusSchema: z$1.ZodEnum<{
453
453
  error: "error";
454
- provisioning: "provisioning";
455
454
  ready: "ready";
455
+ provisioning: "provisioning";
456
456
  creating: "creating";
457
457
  destroyed: "destroyed";
458
458
  }>;
@@ -471,8 +471,8 @@ declare const environmentSchema: z$1.ZodObject<{
471
471
  mergeBaseBranch: z$1.ZodNullable<z$1.ZodString>;
472
472
  status: z$1.ZodEnum<{
473
473
  error: "error";
474
- provisioning: "provisioning";
475
474
  ready: "ready";
475
+ provisioning: "provisioning";
476
476
  creating: "creating";
477
477
  destroyed: "destroyed";
478
478
  }>;
@@ -591,8 +591,8 @@ declare const hostSchema: z$1.ZodObject<{
591
591
  }, z$1.core.$strip>>;
592
592
  }, z$1.core.$strip>;
593
593
  maxPermissionMode: z$1.ZodEnum<{
594
- full: "full";
595
594
  auto: "auto";
595
+ full: "full";
596
596
  "accept-edits": "accept-edits";
597
597
  }>;
598
598
  lastSeenAt: z$1.ZodNullable<z$1.ZodNumber>;
@@ -2961,12 +2961,12 @@ declare const threadEventSchema: z$1.ZodUnion<readonly [z$1.ZodIntersection<z$1.
2961
2961
  }>;
2962
2962
  name: z$1.ZodString;
2963
2963
  source: z$1.ZodEnum<{
2964
- skill: "skill";
2965
2964
  command: "command";
2965
+ skill: "skill";
2966
2966
  }>;
2967
2967
  origin: z$1.ZodEnum<{
2968
- user: "user";
2969
2968
  project: "project";
2969
+ user: "user";
2970
2970
  builtin: "builtin";
2971
2971
  }>;
2972
2972
  label: z$1.ZodString;
@@ -3051,12 +3051,12 @@ declare const threadEventSchema: z$1.ZodUnion<readonly [z$1.ZodIntersection<z$1.
3051
3051
  }>;
3052
3052
  name: z$1.ZodString;
3053
3053
  source: z$1.ZodEnum<{
3054
- skill: "skill";
3055
3054
  command: "command";
3055
+ skill: "skill";
3056
3056
  }>;
3057
3057
  origin: z$1.ZodEnum<{
3058
- user: "user";
3059
3058
  project: "project";
3059
+ user: "user";
3060
3060
  builtin: "builtin";
3061
3061
  }>;
3062
3062
  label: z$1.ZodString;
@@ -3129,8 +3129,8 @@ declare const threadEventSchema: z$1.ZodUnion<readonly [z$1.ZodIntersection<z$1.
3129
3129
  }>;
3130
3130
  permissionMode: z$1.ZodEnum<{
3131
3131
  readonly: "readonly";
3132
- full: "full";
3133
3132
  auto: "auto";
3133
+ full: "full";
3134
3134
  "accept-edits": "accept-edits";
3135
3135
  "workspace-write": "workspace-write";
3136
3136
  }>;
@@ -3928,8 +3928,8 @@ type ReasoningLevel = z$1.infer<typeof reasoningLevelSchema>;
3928
3928
  declare const serviceTierSchema: z$1.ZodString;
3929
3929
  type ServiceTier = z$1.infer<typeof serviceTierSchema>;
3930
3930
  declare const permissionModeSchema: z$1.ZodEnum<{
3931
- full: "full";
3932
3931
  auto: "auto";
3932
+ full: "full";
3933
3933
  "accept-edits": "accept-edits";
3934
3934
  }>;
3935
3935
  type PermissionMode = z$1.infer<typeof permissionModeSchema>;
@@ -3969,12 +3969,12 @@ declare const promptTextMentionSchema: z$1.ZodObject<{
3969
3969
  }>;
3970
3970
  name: z$1.ZodString;
3971
3971
  source: z$1.ZodEnum<{
3972
- skill: "skill";
3973
3972
  command: "command";
3973
+ skill: "skill";
3974
3974
  }>;
3975
3975
  origin: z$1.ZodEnum<{
3976
- user: "user";
3977
3976
  project: "project";
3977
+ user: "user";
3978
3978
  builtin: "builtin";
3979
3979
  }>;
3980
3980
  label: z$1.ZodString;
@@ -4034,12 +4034,12 @@ declare const promptInputSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
4034
4034
  }>;
4035
4035
  name: z$1.ZodString;
4036
4036
  source: z$1.ZodEnum<{
4037
- skill: "skill";
4038
4037
  command: "command";
4038
+ skill: "skill";
4039
4039
  }>;
4040
4040
  origin: z$1.ZodEnum<{
4041
- user: "user";
4042
4041
  project: "project";
4042
+ user: "user";
4043
4043
  builtin: "builtin";
4044
4044
  }>;
4045
4045
  label: z$1.ZodString;
@@ -4098,8 +4098,8 @@ declare const resolvedThreadExecutionOptionsSchema: z$1.ZodObject<{
4098
4098
  serviceTier: z$1.ZodString;
4099
4099
  reasoningLevel: z$1.ZodString;
4100
4100
  permissionMode: z$1.ZodEnum<{
4101
- full: "full";
4102
4101
  auto: "auto";
4102
+ full: "full";
4103
4103
  "accept-edits": "accept-edits";
4104
4104
  }>;
4105
4105
  source: z$1.ZodEnum<{
@@ -4115,8 +4115,8 @@ declare const projectExecutionDefaultsSchema: z$1.ZodObject<{
4115
4115
  serviceTier: z$1.ZodString;
4116
4116
  reasoningLevel: z$1.ZodString;
4117
4117
  permissionMode: z$1.ZodEnum<{
4118
- full: "full";
4119
4118
  auto: "auto";
4119
+ full: "full";
4120
4120
  "accept-edits": "accept-edits";
4121
4121
  }>;
4122
4122
  }, z$1.core.$strip>;
@@ -4156,8 +4156,8 @@ declare const providerInfoSchema: z$1.ZodObject<{
4156
4156
  supportsFork: z$1.ZodBoolean;
4157
4157
  supportsSessionRewind: z$1.ZodBoolean;
4158
4158
  permissionModes: z$1.ZodArray<z$1.ZodEnum<{
4159
- full: "full";
4160
4159
  auto: "auto";
4160
+ full: "full";
4161
4161
  "accept-edits": "accept-edits";
4162
4162
  }>>;
4163
4163
  modelCatalogScope: z$1.ZodEnum<{
@@ -4282,8 +4282,8 @@ declare const threadTimelinePendingTodosSchema: z$1.ZodObject<{
4282
4282
  type ThreadTimelinePendingTodos = z$1.infer<typeof threadTimelinePendingTodosSchema>;
4283
4283
 
4284
4284
  declare const threadParentNotificationsSchema: z$1.ZodEnum<{
4285
- auto: "auto";
4286
4285
  off: "off";
4286
+ auto: "auto";
4287
4287
  stuck: "stuck";
4288
4288
  }>;
4289
4289
  type ThreadParentNotifications = z$1.infer<typeof threadParentNotificationsSchema>;
@@ -4346,12 +4346,12 @@ declare const threadQueuedMessageSchema: z$1.ZodObject<{
4346
4346
  }>;
4347
4347
  name: z$1.ZodString;
4348
4348
  source: z$1.ZodEnum<{
4349
- skill: "skill";
4350
4349
  command: "command";
4350
+ skill: "skill";
4351
4351
  }>;
4352
4352
  origin: z$1.ZodEnum<{
4353
- user: "user";
4354
4353
  project: "project";
4354
+ user: "user";
4355
4355
  builtin: "builtin";
4356
4356
  }>;
4357
4357
  label: z$1.ZodString;
@@ -4397,8 +4397,8 @@ declare const threadQueuedMessageSchema: z$1.ZodObject<{
4397
4397
  model: z$1.ZodString;
4398
4398
  reasoningLevel: z$1.ZodString;
4399
4399
  permissionMode: z$1.ZodEnum<{
4400
- full: "full";
4401
4400
  auto: "auto";
4401
+ full: "full";
4402
4402
  "accept-edits": "accept-edits";
4403
4403
  }>;
4404
4404
  serviceTier: z$1.ZodString;
@@ -7456,8 +7456,8 @@ declare const hostDaemonCommandRegistry: {
7456
7456
  skillFilePath: z$1.ZodString;
7457
7457
  }, z$1.core.$strict>], "kind">>;
7458
7458
  instructionMode: z$1.ZodEnum<{
7459
- replace: "replace";
7460
7459
  append: "append";
7460
+ replace: "replace";
7461
7461
  }>;
7462
7462
  type: z$1.ZodLiteral<"thread.rewind.prepare">;
7463
7463
  leaseId: z$1.ZodString;
@@ -7605,8 +7605,8 @@ declare const hostDaemonCommandRegistry: {
7605
7605
  skillFilePath: z$1.ZodString;
7606
7606
  }, z$1.core.$strict>], "kind">>;
7607
7607
  instructionMode: z$1.ZodEnum<{
7608
- replace: "replace";
7609
7608
  append: "append";
7609
+ replace: "replace";
7610
7610
  }>;
7611
7611
  type: z$1.ZodLiteral<"thread.start">;
7612
7612
  requestId: z$1.ZodString;
@@ -8069,8 +8069,8 @@ declare const hostDaemonCommandRegistry: {
8069
8069
  envPassthrough: z$1.ZodArray<z$1.ZodString>;
8070
8070
  }, z$1.core.$strict>;
8071
8071
  instructionMode: z$1.ZodEnum<{
8072
- replace: "replace";
8073
8072
  append: "append";
8073
+ replace: "replace";
8074
8074
  }>;
8075
8075
  projectId: z$1.ZodString;
8076
8076
  providerId: z$1.ZodString;
@@ -8285,8 +8285,8 @@ declare const hostDaemonCommandRegistry: {
8285
8285
  envPassthrough: z$1.ZodArray<z$1.ZodString>;
8286
8286
  }, z$1.core.$strict>;
8287
8287
  instructionMode: z$1.ZodEnum<{
8288
- replace: "replace";
8289
8288
  append: "append";
8289
+ replace: "replace";
8290
8290
  }>;
8291
8291
  projectId: z$1.ZodString;
8292
8292
  providerId: z$1.ZodString;
@@ -9187,13 +9187,13 @@ declare const hostDaemonCommandRegistry: {
9187
9187
  modifiedAtMs: z$1.ZodOptional<z$1.ZodNumber>;
9188
9188
  sha256: z$1.ZodString;
9189
9189
  }, z$1.core.$strip>, z$1.ZodObject<{
9190
- path: z$1.ZodString;
9191
9190
  contentEncoding: z$1.ZodEnum<{
9192
9191
  base64: "base64";
9193
9192
  utf8: "utf8";
9194
9193
  }>;
9195
9194
  sha256: z$1.ZodString;
9196
9195
  sizeBytes: z$1.ZodNumber;
9196
+ path: z$1.ZodString;
9197
9197
  mimeType: z$1.ZodOptional<z$1.ZodString>;
9198
9198
  modifiedAtMs: z$1.ZodOptional<z$1.ZodNumber>;
9199
9199
  notModified: z$1.ZodLiteral<true>;
@@ -9511,8 +9511,8 @@ declare const hostDaemonCommandRegistry: {
9511
9511
  installed: z$1.ZodBoolean;
9512
9512
  installSource: z$1.ZodEnum<{
9513
9513
  notInstalled: "notInstalled";
9514
- npmGlobal: "npmGlobal";
9515
9514
  external: "external";
9515
+ npmGlobal: "npmGlobal";
9516
9516
  }>;
9517
9517
  currentVersion: z$1.ZodNullable<z$1.ZodString>;
9518
9518
  latestVersion: z$1.ZodNullable<z$1.ZodString>;
@@ -10062,8 +10062,8 @@ declare const providerCliStatusResponseSchema: z$1.ZodRecord<z$1.ZodString, z$1.
10062
10062
  installed: z$1.ZodBoolean;
10063
10063
  installSource: z$1.ZodEnum<{
10064
10064
  notInstalled: "notInstalled";
10065
- npmGlobal: "npmGlobal";
10066
10065
  external: "external";
10066
+ npmGlobal: "npmGlobal";
10067
10067
  }>;
10068
10068
  currentVersion: z$1.ZodNullable<z$1.ZodString>;
10069
10069
  latestVersion: z$1.ZodNullable<z$1.ZodString>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@halcyonlabs/app",
3
- "version": "0.47.0-halcyon.101",
3
+ "version": "0.47.0-halcyon.102",
4
4
  "description": "bb app launcher for npx",
5
5
  "keywords": [
6
6
  "bb",
@@ -22,7 +22,10 @@ START_HEADROOM = 5_000_000_000
22
22
  # to free file entries on filesystems that have a fixed number of them.
23
23
  INODE_FLOOR = 500_000
24
24
  START_INODE_HEADROOM = 500_000
25
- CONCURRENT_JOBS = 2
25
+ MIN_CONCURRENT_JOBS = 2
26
+ MAX_CONCURRENT_JOBS = 8
27
+ JOB_MEMORY_BYTES = 6 * 2**30
28
+ DESKTOP_MEMORY_BYTES = 6 * 2**30
26
29
  CAPACITY_FULL_STATUS = 75
27
30
  LIMITS = dict(retained_bytes=RETAINED_JOB_BYTES)
28
31
  # Records written before the free-space rule carry the old fixed caps. They load
@@ -213,6 +216,61 @@ def write_record(directory, name, value, exclusive=False):
213
216
  raise
214
217
 
215
218
 
219
+ def machine_concurrency(memory, cores, override):
220
+ if override is not None:
221
+ if not re.fullmatch('[0-9]{1,9}', override):
222
+ raise ValueError('Job concurrency override must be a positive whole number.')
223
+ requested = int(override)
224
+ if requested < 1:
225
+ raise ValueError('Job concurrency override must be a positive whole number.')
226
+ slots = max(MIN_CONCURRENT_JOBS, min(MAX_CONCURRENT_JOBS, requested))
227
+ return slots, f'override {requested}; floor {MIN_CONCURRENT_JOBS}, ceiling {MAX_CONCURRENT_JOBS}'
228
+ memory_slots = max(0, memory - DESKTOP_MEMORY_BYTES) // JOB_MEMORY_BYTES
229
+ core_slots = cores // 3
230
+ slots = max(MIN_CONCURRENT_JOBS, min(MAX_CONCURRENT_JOBS, memory_slots, core_slots))
231
+ return slots, (f'{memory / 2**30:.1f} GiB RAM minus 6 GiB for desktop, antfly and main session; '
232
+ f'6 GiB per job gives {memory_slots} slots; {cores} cores / 3 gives {core_slots}; '
233
+ f'floor {MIN_CONCURRENT_JOBS}, ceiling {MAX_CONCURRENT_JOBS}')
234
+
235
+
236
+ def machine_resources():
237
+ if sys.platform == 'darwin':
238
+ import subprocess
239
+ try:
240
+ memory = int(subprocess.check_output(['sysctl', '-n', 'hw.memsize'], timeout=5))
241
+ except subprocess.SubprocessError as error:
242
+ raise OSError('Machine memory reading failed.') from error
243
+ else:
244
+ memory = os.sysconf('SC_PHYS_PAGES') * os.sysconf('SC_PAGE_SIZE')
245
+ cores = os.cpu_count()
246
+ if memory <= 0 or cores is None or cores <= 0:
247
+ raise ValueError('Machine memory or core count is unavailable.')
248
+ return memory, cores
249
+
250
+
251
+ def concurrent_jobs(state):
252
+ try:
253
+ fd = os.open('concurrency', os.O_RDONLY | os.O_NOFOLLOW | os.O_CLOEXEC | os.O_NONBLOCK, dir_fd=state)
254
+ except FileNotFoundError:
255
+ override = None
256
+ else:
257
+ with os.fdopen(fd) as stream:
258
+ metadata = os.fstat(stream.fileno())
259
+ if not stat.S_ISREG(metadata.st_mode) or metadata.st_size > 32:
260
+ raise ValueError('Invalid job concurrency override file.')
261
+ override = stream.read(33).strip()
262
+ try:
263
+ memory, cores = machine_resources()
264
+ slots, reason = machine_concurrency(memory, cores, override)
265
+ except (OSError, ValueError) as error:
266
+ if override is not None:
267
+ slots, reason = machine_concurrency(0, 0, override)
268
+ else:
269
+ slots, reason = MIN_CONCURRENT_JOBS, f'machine reading unavailable: {error}; floor {MIN_CONCURRENT_JOBS}'
270
+ print(f'Job concurrency: {slots}; {reason}.', file=sys.stderr)
271
+ return slots
272
+
273
+
216
274
  class Workspaces:
217
275
  """A single supervisor owns these roots, inaccessible to workers.
218
276
 
@@ -279,7 +337,7 @@ class Workspaces:
279
337
  self.environment(existing['id'])
280
338
  return existing
281
339
  slots = [r for r in records if holds_slot(r)]
282
- if len(slots) >= CONCURRENT_JOBS:
340
+ if len(slots) >= concurrent_jobs(self.state):
283
341
  raise CapacityFull('Job capacity is reserved; wait for disposal.')
284
342
  if not workspace:
285
343
  if type(free) is not int or free < MAIN_FREE_FLOOR:
@@ -528,7 +586,7 @@ class Workspaces:
528
586
  return manifest
529
587
  if manifest['state'] != 'parked':
530
588
  raise ValueError('Only a parked job can take a slot again.')
531
- if len([r for r in self.records() if holds_slot(r)]) >= CONCURRENT_JOBS:
589
+ if len([r for r in self.records() if holds_slot(r)]) >= concurrent_jobs(self.state):
532
590
  raise CapacityFull('Job capacity is reserved; wait for disposal.')
533
591
  return self.save_transition(manifest, 'running')
534
592
 
@@ -1267,6 +1325,10 @@ def managed_operation(store, account, request):
1267
1325
  finally:
1268
1326
  os.close(root)
1269
1327
  elif request['operation'] == 'measure':
1328
+ try:
1329
+ concurrent_jobs(store.state)
1330
+ except (OSError, ValueError) as error:
1331
+ print(f'Job concurrency setting could not be read: {error}', file=sys.stderr)
1270
1332
  if request.get('size', True) not in (True, False):
1271
1333
  raise ValueError('Invalid measure request.')
1272
1334
  print(json.dumps(store.measure(request['id'], sized=request.get('size', True))))
@@ -1 +1 @@
1
- f1059d04b641d9927b443da4711ba9c7639a9d7b
1
+ 7e8f8d1775099aa18db90f3e32a42f00d3947c08