@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 +13 -4
- package/dist/kernel-companion.mjs +116 -10
- package/package.json +1 -1
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.
|
|
4
|
-
|
|
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.
|
|
28
|
-
|
|
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
|
-
|
|
22446
|
-
|
|
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
|
-
|
|
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.
|
|
23352
|
+
`${false ? "development" : "0.1.1"}
|
|
23247
23353
|
`
|
|
23248
23354
|
);
|
|
23249
23355
|
return;
|