@supercorks/krnl 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  # Kernel CLI
2
2
 
3
- Connect [Kernel](https://app.krnl.work) to Codex on your Mac. Start a task from Kernel in Plan or
4
- Work mode, then open the same task in Codex. Conversations and approvals stay in Codex; Kernel
3
+ Connect [Kernel](https://app.krnl.work) to Codex on your Mac. Choose **Launch in Codex** on a Kernel task, review Plan/Work mode, destination, model, reasoning,
4
+ and folder options in the popup, then open the same task in Codex. Conversations and approvals stay in Codex; Kernel
5
5
  shows execution status and a direct link.
6
6
 
7
7
  ## Install and connect
@@ -14,6 +14,8 @@ krnl login
14
14
  krnl connect codex
15
15
  ```
16
16
 
17
+ If pnpm reports `ERR_PNPM_NO_GLOBAL_BIN_DIR`, run `pnpm setup`, open a new Terminal tab, and retry the install.
18
+
17
19
  `krnl login` opens Kernel in your default browser. Sign in with your invited Kernel account and
18
20
  choose **Connect CLI**. Return to Terminal when the browser says the login is finishing.
19
21
 
@@ -24,8 +26,12 @@ instructions if the new hooks need review. Review the eight Kernel hooks and res
24
26
  tasks afterward. The companion detects completed review automatically.
25
27
 
26
28
  Open **Settings → Integrations → Codex** in Kernel to map an organization or project to a saved
27
- Codex project. Your Mac and saved projects appear automatically. Launches stay disabled until setup
28
- is ready; one unavailable project does not disable healthy projects.
29
+ Codex project. Your Mac and saved projects appear automatically. Each connection card contains its organization and
30
+ project mappings. Choose **Add mapping** or **Edit** to set the destination, model, and reasoning.
31
+ New mappings default to **GPT-6 Astra · xhigh**; choices come from that Mac’s current Codex model
32
+ catalog. Launches stay disabled until setup is ready; one unavailable project does not disable
33
+ healthy projects. **Delete connection** revokes its authorization and removes its mappings, while
34
+ keeping existing tasks, handoff history, receipts, and worktrees.
29
35
 
30
36
  No repository checkout, build tools, copied IDs, or per-folder authorization commands are needed.
31
37
  Installing the npm package alone does not start a service or change Codex configuration.
@@ -50,6 +56,9 @@ pnpm add -g @supercorks/krnl@latest
50
56
  krnl connect codex
51
57
  ```
52
58
 
59
+ Version **0.1.1 or later** is required to launch with mapping model and reasoning settings.
60
+ Kernel explains when an older companion needs this update; existing task monitoring continues.
61
+
53
62
  Repeated connection reuses the machine identity. Review changed hook commands in `/hooks` if Node
54
63
  moved. After updating Node, run `krnl connect codex` to refresh the service’s executable path.
55
64
 
@@ -22061,6 +22061,25 @@ var reconcileTogglEntrySchema = external_exports.discriminatedUnion("action", [
22061
22061
 
22062
22062
  // ../domain/src/codex.ts
22063
22063
  var CODEX_PROTOCOL_VERSION = 1;
22064
+ var CODEX_DEFAULT_MODEL = "gpt-6-astra";
22065
+ var CODEX_DEFAULT_REASONING_EFFORT = "xhigh";
22066
+ var CODEX_REASONING_EFFORTS = [
22067
+ "none",
22068
+ "minimal",
22069
+ "low",
22070
+ "medium",
22071
+ "high",
22072
+ "xhigh",
22073
+ "max",
22074
+ "ultra"
22075
+ ];
22076
+ var codexReasoningEffortSchema = external_exports.enum(CODEX_REASONING_EFFORTS);
22077
+ var codexModelIdSchema = external_exports.string().trim().min(1).max(200).regex(/^[A-Za-z0-9][A-Za-z0-9._:/-]*$/);
22078
+ var codexModelSchema = external_exports.strictObject({
22079
+ id: codexModelIdSchema,
22080
+ label: external_exports.string().trim().min(1).max(200),
22081
+ reasoningEfforts: external_exports.array(codexReasoningEffortSchema).min(1).max(CODEX_REASONING_EFFORTS.length)
22082
+ });
22064
22083
  var protocolVersion = external_exports.literal(CODEX_PROTOCOL_VERSION);
22065
22084
  var sequence = external_exports.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
22066
22085
  var identity = external_exports.string().min(1).max(200);
@@ -22078,6 +22097,9 @@ var codexCatalogProjectSchema = external_exports.strictObject({
22078
22097
  var codexHealthSchema = external_exports.strictObject({
22079
22098
  reachable: external_exports.boolean(),
22080
22099
  hooksReady: external_exports.boolean(),
22100
+ // Older companions cannot parse model settings in strict launch payloads.
22101
+ supportsModelSelection: external_exports.boolean().optional(),
22102
+ models: external_exports.array(codexModelSchema).max(100).optional(),
22081
22103
  appServerVersion: external_exports.string().max(100),
22082
22104
  desktopVersion: external_exports.string().max(100),
22083
22105
  issue: external_exports.string().max(500).nullable()
@@ -22103,6 +22125,8 @@ var saveCodexMappingSchema = external_exports.strictObject({
22103
22125
  machineId: external_exports.uuid(),
22104
22126
  projectId: identity,
22105
22127
  checkout: codexCheckoutSchema,
22128
+ model: codexModelIdSchema.default(CODEX_DEFAULT_MODEL),
22129
+ reasoningEffort: codexReasoningEffortSchema.default(CODEX_DEFAULT_REASONING_EFFORT),
22106
22130
  version: sequence.default(0)
22107
22131
  });
22108
22132
  var deleteCodexMappingSchema = external_exports.strictObject({
@@ -22116,6 +22140,9 @@ var launchCodexTaskSchema = external_exports.strictObject({
22116
22140
  taskId: external_exports.uuid(),
22117
22141
  taskVersion: external_exports.number().int().positive(),
22118
22142
  mode: codexModeSchema,
22143
+ model: codexModelIdSchema.optional(),
22144
+ reasoningEffort: codexReasoningEffortSchema.optional(),
22145
+ checkout: codexCheckoutSchema.optional(),
22119
22146
  override: external_exports.strictObject({ machineId: external_exports.uuid(), projectId: identity }).optional()
22120
22147
  });
22121
22148
  var codexLaunchSchema = external_exports.strictObject({
@@ -22125,6 +22152,8 @@ var codexLaunchSchema = external_exports.strictObject({
22125
22152
  mode: codexModeSchema,
22126
22153
  destination: codexCatalogProjectSchema,
22127
22154
  checkout: codexCheckoutSchema,
22155
+ model: codexModelIdSchema.optional(),
22156
+ reasoningEffort: codexReasoningEffortSchema.optional(),
22128
22157
  submittedAt: external_exports.iso.datetime(),
22129
22158
  expiresAt: external_exports.iso.datetime(),
22130
22159
  task: external_exports.strictObject({
@@ -22269,6 +22298,71 @@ var settingsHealthSnapshotSchema = external_exports.object({
22269
22298
  })
22270
22299
  });
22271
22300
 
22301
+ // src/models.ts
22302
+ var messages = {
22303
+ catalog: "Codex's model catalog could not be read. Reconnect the companion and try again.",
22304
+ model: "The selected model is unavailable on this Mac. Choose another model in Codex settings.",
22305
+ effort: "The selected model does not support this reasoning effort. Update the Codex settings and try again."
22306
+ };
22307
+ var CodexModelSelectionError = class extends Error {
22308
+ constructor(reason) {
22309
+ super(messages[reason]);
22310
+ }
22311
+ };
22312
+ var modelPageSchema = external_exports.object({
22313
+ data: external_exports.array(
22314
+ external_exports.object({
22315
+ model: codexModelIdSchema,
22316
+ displayName: external_exports.string().trim().min(1),
22317
+ supportedReasoningEfforts: external_exports.array(external_exports.object({ reasoningEffort: external_exports.string() }))
22318
+ })
22319
+ ),
22320
+ nextCursor: external_exports.string().min(1).nullable().optional()
22321
+ });
22322
+ async function discoverModels(server) {
22323
+ try {
22324
+ const models = /* @__PURE__ */ new Map();
22325
+ const cursors = /* @__PURE__ */ new Set();
22326
+ let cursor;
22327
+ do {
22328
+ const page = modelPageSchema.parse(
22329
+ await server.call("model/list", { limit: 100, ...cursor ? { cursor } : {} }, 5e3)
22330
+ );
22331
+ for (const model of page.data) {
22332
+ const reasoningEfforts = model.supportedReasoningEfforts.flatMap((option) => {
22333
+ const parsed = codexReasoningEffortSchema.safeParse(option.reasoningEffort);
22334
+ return parsed.success ? [parsed.data] : [];
22335
+ });
22336
+ if (!reasoningEfforts.length) continue;
22337
+ models.set(model.model, {
22338
+ id: model.model,
22339
+ label: model.displayName.slice(0, 200),
22340
+ reasoningEfforts: [...new Set(reasoningEfforts)]
22341
+ });
22342
+ if (models.size > 100) throw new CodexModelSelectionError("catalog");
22343
+ }
22344
+ cursor = page.nextCursor ?? void 0;
22345
+ if (cursor) {
22346
+ if (cursors.has(cursor) || cursors.size >= 100)
22347
+ throw new CodexModelSelectionError("catalog");
22348
+ cursors.add(cursor);
22349
+ }
22350
+ } while (cursor);
22351
+ return [...models.values()];
22352
+ } catch {
22353
+ throw new CodexModelSelectionError("catalog");
22354
+ }
22355
+ }
22356
+ function resolveModelSelection(launch, models) {
22357
+ const model = launch.model ?? CODEX_DEFAULT_MODEL;
22358
+ const reasoningEffort = launch.reasoningEffort ?? CODEX_DEFAULT_REASONING_EFFORT;
22359
+ const available = models.find((candidate) => candidate.id === model);
22360
+ if (!available) throw new CodexModelSelectionError("model");
22361
+ if (!available.reasoningEfforts.includes(reasoningEffort))
22362
+ throw new CodexModelSelectionError("effort");
22363
+ return { model, reasoningEffort };
22364
+ }
22365
+
22272
22366
  // src/runtime.ts
22273
22367
  var sourceMarker = (id) => `kernel-handoff:${id}`;
22274
22368
  function initialReceipt(launch) {
@@ -22353,6 +22447,8 @@ async function runCompanion(machineId, entrypoint2, signal) {
22353
22447
  let health = {
22354
22448
  reachable: false,
22355
22449
  hooksReady: false,
22450
+ supportsModelSelection: true,
22451
+ models: [],
22356
22452
  appServerVersion: "",
22357
22453
  desktopVersion: "",
22358
22454
  issue: "Checking Codex compatibility."
@@ -22418,16 +22514,22 @@ async function runCompanion(machineId, entrypoint2, signal) {
22418
22514
  () => queue.push({ launchId: launch.id, event: { method: "kernel/closed" } })
22419
22515
  );
22420
22516
  await owner.initialize();
22517
+ const selection = resolveModelSelection(launch, await discoverModels(owner));
22518
+ if (!canBegin(receipt, Date.now() + clockOffset))
22519
+ throw new Error("The launch expired while checking model availability");
22520
+ receipt.model = selection.model;
22521
+ receipt.effort = selection.reasoningEffort;
22421
22522
  receipt.phase = "creating";
22422
22523
  await save(receipt);
22423
22524
  const created = await owner.call("thread/start", {
22424
22525
  cwd: receipt.cwd,
22425
22526
  projectId: project.id,
22426
- threadSource: sourceMarker(launch.id)
22527
+ threadSource: sourceMarker(launch.id),
22528
+ model: selection.model,
22529
+ config: { model_reasoning_effort: selection.reasoningEffort },
22530
+ allowProviderModelFallback: false
22427
22531
  });
22428
22532
  receipt.threadId = created.thread.id;
22429
- receipt.model = created.model;
22430
- receipt.effort = created.reasoningEffort ?? null;
22431
22533
  receipt.phase = "created";
22432
22534
  await save(receipt);
22433
22535
  await indexThreads();
@@ -22442,14 +22544,14 @@ async function runCompanion(machineId, entrypoint2, signal) {
22442
22544
  input: [{ type: "text", text: codexLaunchPrompt(launch) }],
22443
22545
  collaborationMode: collaborationMode(
22444
22546
  launch.mode,
22445
- created.model,
22446
- created.reasoningEffort ?? null
22547
+ selection.model,
22548
+ selection.reasoningEffort
22447
22549
  )
22448
22550
  });
22449
22551
  receipt.turnId = response.turn.id;
22450
22552
  receipt.status.turnId = response.turn.id;
22451
22553
  await save(receipt);
22452
- } catch {
22554
+ } catch (error51) {
22453
22555
  try {
22454
22556
  await owners.get(launch.id)?.stop();
22455
22557
  } catch {
@@ -22474,7 +22576,7 @@ async function runCompanion(machineId, entrypoint2, signal) {
22474
22576
  };
22475
22577
  } else {
22476
22578
  receipt.ambiguous = receipt.phase === "creating";
22477
- receipt.failure = receipt.ambiguous ? "Confirming whether Codex created the task. This launch will not be repeated." : "The task could not start. Check the locally authorized project and checkout policy.";
22579
+ receipt.failure = receipt.ambiguous ? "Confirming whether Codex created the task. This launch will not be repeated." : error51 instanceof CodexModelSelectionError ? error51.message : "The task could not start. Check the locally authorized project and checkout policy.";
22478
22580
  if (!receipt.ambiguous) receipt.phase = "failed";
22479
22581
  }
22480
22582
  await save(receipt);
@@ -22518,21 +22620,25 @@ async function runCompanion(machineId, entrypoint2, signal) {
22518
22620
  "Print:CFBundleShortVersionString",
22519
22621
  "/Applications/ChatGPT.app/Contents/Info.plist"
22520
22622
  ]).then((result) => result.stdout.trim()).catch(() => "");
22623
+ const models = await discoverModels(observer);
22521
22624
  health = {
22522
22625
  reachable: true,
22523
22626
  hooksReady: ready,
22627
+ supportsModelSelection: true,
22628
+ models,
22524
22629
  appServerVersion: stdout.trim(),
22525
22630
  desktopVersion: desktop,
22526
22631
  issue: ready ? null : "Review the eight Kernel hooks using /hooks in Codex CLI. The companion detects completed review automatically."
22527
22632
  };
22528
- } catch {
22633
+ } catch (error51) {
22529
22634
  observer?.close();
22530
22635
  observer = void 0;
22531
22636
  health = {
22532
22637
  ...health,
22533
22638
  reachable: false,
22534
22639
  hooksReady: false,
22535
- issue: "Codex could not be reached through its supported app-server interface."
22640
+ models: [],
22641
+ issue: error51 instanceof CodexModelSelectionError ? error51.message : "Codex could not be reached through its supported app-server interface."
22536
22642
  };
22537
22643
  }
22538
22644
  try {
@@ -23243,7 +23349,7 @@ async function main() {
23243
23349
  }
23244
23350
  if (command === "--version") {
23245
23351
  process.stdout.write(
23246
- `${false ? "development" : "0.1.0"}
23352
+ `${false ? "development" : "0.1.1"}
23247
23353
  `
23248
23354
  );
23249
23355
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supercorks/krnl",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Connect Kernel to Codex on your Mac",
5
5
  "type": "module",
6
6
  "bin": {