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

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
@@ -155,10 +155,10 @@ declare const uiPreferenceDefinitions: {
155
155
  }>>;
156
156
  readonly "sidebar.threadGrouping.environment": UiPreferenceDefinition<z$1.ZodUnion<readonly [z$1.ZodLiteral<"auto">, z$1.ZodBoolean]>>;
157
157
  readonly "sidebar.chronologicalSort": UiPreferenceDefinition<z$1.ZodEnum<{
158
+ none: "none";
158
159
  updated: "updated";
159
160
  created: "created";
160
161
  alpha: "alpha";
161
- none: "none";
162
162
  }>>;
163
163
  readonly "sidebar.sortDirection": UiPreferenceDefinition<z$1.ZodEnum<{
164
164
  default: "default";
@@ -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
  }>;
@@ -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>;
@@ -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;
@@ -9192,9 +9192,9 @@ declare const hostDaemonCommandRegistry: {
9192
9192
  base64: "base64";
9193
9193
  utf8: "utf8";
9194
9194
  }>;
9195
- sha256: z$1.ZodString;
9196
- sizeBytes: z$1.ZodNumber;
9197
9195
  mimeType: z$1.ZodOptional<z$1.ZodString>;
9196
+ sizeBytes: z$1.ZodNumber;
9197
+ sha256: z$1.ZodString;
9198
9198
  modifiedAtMs: z$1.ZodOptional<z$1.ZodNumber>;
9199
9199
  notModified: z$1.ZodLiteral<true>;
9200
9200
  }, z$1.core.$strip>]>, "onlineRpc", true>;
@@ -9459,10 +9459,10 @@ declare const hostDaemonCommandRegistry: {
9459
9459
  health: z$1.ZodObject<{
9460
9460
  status: z$1.ZodEnum<{
9461
9461
  unknown: "unknown";
9462
- ready: "ready";
9463
9462
  not_installed: "not_installed";
9464
9463
  unauthenticated: "unauthenticated";
9465
9464
  expired: "expired";
9465
+ ready: "ready";
9466
9466
  unsupported_version: "unsupported_version";
9467
9467
  }>;
9468
9468
  statusMessage: z$1.ZodNullable<z$1.ZodString>;
@@ -9510,9 +9510,9 @@ declare const hostDaemonCommandRegistry: {
9510
9510
  executablePath: z$1.ZodNullable<z$1.ZodString>;
9511
9511
  installed: z$1.ZodBoolean;
9512
9512
  installSource: z$1.ZodEnum<{
9513
+ external: "external";
9513
9514
  notInstalled: "notInstalled";
9514
9515
  npmGlobal: "npmGlobal";
9515
- external: "external";
9516
9516
  }>;
9517
9517
  currentVersion: z$1.ZodNullable<z$1.ZodString>;
9518
9518
  latestVersion: z$1.ZodNullable<z$1.ZodString>;
@@ -9958,8 +9958,8 @@ declare const hostDaemonCommandRegistry: {
9958
9958
  message: z$1.ZodNullable<z$1.ZodString>;
9959
9959
  state: z$1.ZodNullable<z$1.ZodEnum<{
9960
9960
  pending: "pending";
9961
- activating: "activating";
9962
9961
  ready: "ready";
9962
+ activating: "activating";
9963
9963
  }>>;
9964
9964
  }, z$1.core.$strict>, "onlineRpc", true>;
9965
9965
  "server_move.prepare": HostDaemonCommandDescriptor<"server_move.prepare", z$1.ZodObject<{
@@ -10061,9 +10061,9 @@ declare const providerCliStatusResponseSchema: z$1.ZodRecord<z$1.ZodString, z$1.
10061
10061
  executablePath: z$1.ZodNullable<z$1.ZodString>;
10062
10062
  installed: z$1.ZodBoolean;
10063
10063
  installSource: z$1.ZodEnum<{
10064
+ external: "external";
10064
10065
  notInstalled: "notInstalled";
10065
10066
  npmGlobal: "npmGlobal";
10066
- external: "external";
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.106",
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))))
@@ -57,9 +57,9 @@ After=network.target
57
57
  User=vectors
58
58
  Group=vectors
59
59
  Environment=HOME=/var/db/orbit/vectors
60
- # The embedding model is loaded at start (about two minutes on two vCPUs): loaded on
61
- # demand, the first index creation's probe times out while it loads.
62
- ExecStart=/usr/local/bin/antfly standalone --host 127.0.0.1 --port 8080 --health-port 4200 --data-dir $data --models-dir $models --preload-model embedder:$model
60
+ ExecStart=/usr/local/bin/antfly standalone --host 127.0.0.1 --port 8080 --health-port 4200 --data-dir $data --models-dir $models --process-memory-budget-mb 6144 --inference-kv-budget-mb 64 --preload-model embedder:$model
61
+ MemoryAccounting=true
62
+ MemoryMax=6144M
63
63
  Restart=always
64
64
  RestartSec=3
65
65
  NoNewPrivileges=true
@@ -1 +1 @@
1
- f1059d04b641d9927b443da4711ba9c7639a9d7b
1
+ 204aea94877ae0fdc63ccee1e6e19e67f309dc03