@supercorks/krnl 0.1.5 → 0.1.7

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
@@ -59,6 +59,12 @@ krnl connect codex
59
59
  Version **0.1.1 or later** is required to launch with mapping model and reasoning settings.
60
60
  Version **0.1.2 or later** also supports linking an existing Codex task.
61
61
  Version **0.1.5 or later** adds durable delivery recovery, cancellation support, and task-status freshness when the Kernel server supports it.
62
+ Version **0.1.6 or later** recognizes interrupted turns with a saved completion timestamp as Done
63
+ with “Stopped in Codex.”, including after reconnecting. An interrupted status without that timestamp
64
+ remains uncertain because it can also describe a turn still running in desktop.
65
+ Version **0.1.7 or later** keeps the Kernel card's title synchronized with renames in Codex,
66
+ including completed tasks, when the server supports it. This does not rename the Kernel task.
67
+ Status and explanatory text share one row, for example **Done · Stopped in Codex.**
62
68
  Version **0.1.3 or later** supports mapping task name prefixes. For example, a prefix of `👩‍⚕️`
63
69
  creates `👩‍⚕️ MELLA-284: Investigate an issue`. A blank prefix keeps the normal name. Project
64
70
  mapping settings take precedence over organization settings, and changes apply only to new tasks.
@@ -22143,6 +22143,20 @@ var acceptAsanaSuggestionSchema = external_exports.object({
22143
22143
  existingTaskId: external_exports.uuid().optional(),
22144
22144
  syncProjectGid: asanaGidSchema.nullable().optional()
22145
22145
  }).strict();
22146
+ var linkKernelTaskToAsanaSchema = external_exports.object({
22147
+ sourceId: external_exports.uuid(),
22148
+ asanaTaskGid: external_exports.string().regex(/^\d+$/).optional(),
22149
+ syncProjectGid: external_exports.string().regex(/^\d+$/).nullable().optional(),
22150
+ create: external_exports.object({
22151
+ title: external_exports.string().trim().min(1).max(500),
22152
+ description: external_exports.string().max(5e4).optional(),
22153
+ projectGid: external_exports.string().regex(/^\d+$/),
22154
+ assigneeGid: external_exports.union([external_exports.literal("me"), external_exports.string().regex(/^\d+$/)]).nullable().optional()
22155
+ }).strict().optional()
22156
+ }).strict().refine(
22157
+ (input) => Boolean(input.asanaTaskGid) !== Boolean(input.create),
22158
+ "Choose an existing Asana task or create a new one"
22159
+ );
22146
22160
 
22147
22161
  // ../domain/src/invoicing.ts
22148
22162
  var invoicePresentationSchema = external_exports.enum([
@@ -22461,6 +22475,7 @@ var cancelCodexOperationSchema = external_exports.strictObject({
22461
22475
  kind: external_exports.enum(["launch", "lookup"])
22462
22476
  });
22463
22477
  var codexStatusReportSchema = external_exports.strictObject({
22478
+ title: external_exports.string().trim().min(1).max(300).optional(),
22464
22479
  observationAgeMs: external_exports.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).optional(),
22465
22480
  launchId: external_exports.uuid(),
22466
22481
  sequence,
@@ -22766,6 +22781,13 @@ var sourceKinds = [
22766
22781
  "subAgentOther",
22767
22782
  "unknown"
22768
22783
  ];
22784
+ async function readThreadTitle(server, threadId) {
22785
+ const { thread } = external_exports.object({
22786
+ thread: external_exports.object({ id: external_exports.uuid(), name: external_exports.string().nullable().optional() })
22787
+ }).parse(await server.call("thread/read", { threadId, includeTurns: false }, 2e3));
22788
+ if (thread.id !== threadId) throw new Error("Codex returned a different task");
22789
+ return thread.name === void 0 ? void 0 : thread.name?.trim().slice(0, 300) || "Untitled task";
22790
+ }
22769
22791
  var inside = (root, folder) => {
22770
22792
  const path = relative(root, folder);
22771
22793
  return !isAbsolute2(path) && path !== ".." && !path.startsWith("../");
@@ -23168,6 +23190,7 @@ async function runCompanion(machineId, entrypoint2, signal) {
23168
23190
  };
23169
23191
  let refreshed = 0;
23170
23192
  let supportsFreshness = false;
23193
+ let supportsTaskTitles = false;
23171
23194
  let heartbeatHealth = "";
23172
23195
  const laneRetries = /* @__PURE__ */ new Map();
23173
23196
  let fatalError = null;
@@ -23427,6 +23450,7 @@ async function runCompanion(machineId, entrypoint2, signal) {
23427
23450
  monotonic: performance.now()
23428
23451
  };
23429
23452
  supportsFreshness = response.capabilities?.statusFreshness === true;
23453
+ supportsTaskTitles = response.capabilities?.taskTitles === true;
23430
23454
  heartbeatHealth = JSON.stringify(health);
23431
23455
  refreshed = performance.now();
23432
23456
  schedule("launches", 2e3, launches);
@@ -23612,6 +23636,9 @@ async function runCompanion(machineId, entrypoint2, signal) {
23612
23636
  4,
23613
23637
  (receipt) => writers.run(receipt.launch.id, async () => {
23614
23638
  inspected.set(receipt.launch.id, performance.now());
23639
+ const title = await readThreadTitle(observer, receipt.threadId).catch(() => void 0);
23640
+ const titleChanged = title !== void 0 && title !== receipt.threadTitle;
23641
+ if (titleChanged) receipt.threadTitle = title;
23615
23642
  try {
23616
23643
  if (owners.has(receipt.launch.id) && receipt.phase !== "released") {
23617
23644
  observe(receipt);
@@ -23625,15 +23652,16 @@ async function runCompanion(machineId, entrypoint2, signal) {
23625
23652
  2e3
23626
23653
  );
23627
23654
  const turn = data[0];
23655
+ const interrupted = turn?.status === "interrupted" && Number.isFinite(turn.completedAt);
23628
23656
  const matchesActive = receipt.status.state !== "running" || turn?.id === receipt.status.turnId;
23629
23657
  const alive = await observedProcessAlive(receipt.pid, receipt.nativeIdentity);
23630
- if (turn && ["completed", "failed"].includes(turn.status) && matchesActive && !receipt.status.waiting) {
23658
+ if (turn && (["completed", "failed"].includes(turn.status) || interrupted) && matchesActive && !receipt.status.waiting) {
23631
23659
  receipt.status = {
23632
23660
  ...receipt.status,
23633
23661
  state: "done",
23634
23662
  waiting: false,
23635
23663
  turnId: turn.id,
23636
- message: turn.status === "failed" ? "Codex ended this turn with an error. Open the task for details." : null
23664
+ message: turn.status === "failed" ? "Codex ended this turn with an error. Open the task for details." : interrupted ? "Stopped in Codex." : null
23637
23665
  };
23638
23666
  observe(receipt);
23639
23667
  } else if ((receipt.handoffWaiting || receipt.hookAt && alive) && receipt.status.state === "running") {
@@ -23649,6 +23677,10 @@ async function runCompanion(machineId, entrypoint2, signal) {
23649
23677
  receipt.status.sequence++;
23650
23678
  await save(receipt);
23651
23679
  } catch {
23680
+ if (titleChanged) {
23681
+ receipt.status.sequence++;
23682
+ await save(receipt);
23683
+ }
23652
23684
  observer?.close();
23653
23685
  observer = void 0;
23654
23686
  }
@@ -23687,6 +23719,7 @@ async function runCompanion(machineId, entrypoint2, signal) {
23687
23719
  reports: [
23688
23720
  {
23689
23721
  ...snapshot.status,
23722
+ ...supportsTaskTitles && snapshot.threadTitle ? { title: snapshot.threadTitle } : {},
23690
23723
  ...supportsFreshness ? {
23691
23724
  observationAgeMs: Math.ceil(
23692
23725
  observationAge + Math.max(0, performance.now() - snapshotAt)
@@ -24418,7 +24451,7 @@ async function main() {
24418
24451
  }
24419
24452
  if (command === "--version") {
24420
24453
  process.stdout.write(
24421
- `${false ? "development" : "0.1.5"}
24454
+ `${false ? "development" : "0.1.7"}
24422
24455
  `
24423
24456
  );
24424
24457
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supercorks/krnl",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Connect Kernel to Codex on your Mac",
5
5
  "type": "module",
6
6
  "bin": {