neko-harness 0.5.0 → 0.5.2

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.
@@ -43,7 +43,7 @@
43
43
  href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' rx='26' fill='%23ffb7c5'/%3E%3Ctext x='50' y='70' font-size='58' text-anchor='middle' fill='%23ffffff' font-family='sans-serif' font-weight='bold'%3En%3C/text%3E%3C/svg%3E"
44
44
  />
45
45
  <title>neko harness</title>
46
- <script type="module" crossorigin src="/assets/index-v4Ct9JMn.js"></script>
46
+ <script type="module" crossorigin src="/assets/index-PcV-h5ox.js"></script>
47
47
  <link rel="stylesheet" crossorigin href="/assets/index-DCZeTvcw.css">
48
48
  </head>
49
49
  <body>
package/dist/gateway.js CHANGED
@@ -16767,11 +16767,24 @@ function compactionPolicy(state, windows) {
16767
16767
  if (sources.compaction.keepRecentTokens !== "default")
16768
16768
  policy.keepRecentTokens = effective.compaction.keepRecentTokens;
16769
16769
  const percent = effective.compaction.triggerPercent;
16770
- const window2 = windows.length > 0 ? Math.min(...windows) : 0;
16771
- if (percent !== null && window2 > 0)
16772
- policy.reserveTokens = window2 - Math.floor(window2 * percent / 100);
16770
+ if (percent === null)
16771
+ return policy;
16772
+ const overrides = {};
16773
+ for (const [id, window2] of windows)
16774
+ if (window2 > 0)
16775
+ overrides[id] = { reserveTokens: window2 - Math.floor(window2 * percent / 100) };
16776
+ if (Object.keys(overrides).length > 0)
16777
+ policy.modelOverrides = overrides;
16773
16778
  return policy;
16774
16779
  }
16780
+ function createCompactionPolicy(windows) {
16781
+ let last;
16782
+ return (state) => {
16783
+ if (last?.state !== state)
16784
+ last = { state, policy: compactionPolicy(state, windows) };
16785
+ return last.policy;
16786
+ };
16787
+ }
16775
16788
 
16776
16789
  // packages/core/src/search-providers.ts
16777
16790
  var SEARCH_PROVIDERS = ["tavily", "deepseek"];
@@ -17735,6 +17748,7 @@ import { defineDoc } from "@earendil-works/pi-durable";
17735
17748
  var PLAN_HISTORY = 5;
17736
17749
  var PlanDoc = defineDoc({
17737
17750
  kind: "app.neko.plan",
17751
+ checkpointWhen: () => false,
17738
17752
  version: 1,
17739
17753
  scope: "conversation",
17740
17754
  history: "rewindable",
@@ -17789,6 +17803,7 @@ function subagentUsageTotals(state) {
17789
17803
  var agentIdFor = (childId) => `agent-${childId}`;
17790
17804
  var DelegationsDoc = defineDoc2({
17791
17805
  kind: "app.neko.delegations",
17806
+ checkpointWhen: () => false,
17792
17807
  version: 1,
17793
17808
  scope: "conversation",
17794
17809
  history: "latest",
@@ -17797,6 +17812,7 @@ var DelegationsDoc = defineDoc2({
17797
17812
  });
17798
17813
  var SubagentsDoc = defineDoc2({
17799
17814
  kind: "app.neko.subagents",
17815
+ checkpointWhen: () => false,
17800
17816
  version: 1,
17801
17817
  scope: "conversation",
17802
17818
  history: "latest",
@@ -17805,6 +17821,7 @@ var SubagentsDoc = defineDoc2({
17805
17821
  });
17806
17822
  var SubagentDoc = defineDoc2({
17807
17823
  kind: "app.neko.subagent",
17824
+ checkpointWhen: () => false,
17808
17825
  version: 1,
17809
17826
  scope: "conversation",
17810
17827
  history: "latest",
@@ -17813,6 +17830,7 @@ var SubagentDoc = defineDoc2({
17813
17830
  });
17814
17831
  var SlotsDoc = defineDoc2({
17815
17832
  kind: "app.neko.subagent-slots",
17833
+ checkpointWhen: () => false,
17816
17834
  version: 1,
17817
17835
  scope: "session",
17818
17836
  initial: () => ({ items: [] })
@@ -17971,6 +17989,23 @@ var structuredOutputSchema = Type.Union([
17971
17989
  next: Type.Union([Type.Integer(), Type.Null()])
17972
17990
  }, { additionalProperties: false })
17973
17991
  ]);
17992
+ var ADMISSION_POLL_MS = 100;
17993
+ function pause(runtime, ms) {
17994
+ const { signal } = runtime;
17995
+ return new Promise((resolve, reject) => {
17996
+ if (signal.aborted)
17997
+ return reject(signal.reason);
17998
+ const disarm = runtime.setTimer(() => {
17999
+ signal.removeEventListener("abort", abort);
18000
+ resolve();
18001
+ }, ms);
18002
+ const abort = () => {
18003
+ disarm();
18004
+ reject(signal.reason);
18005
+ };
18006
+ signal.addEventListener("abort", abort, { once: true });
18007
+ });
18008
+ }
17974
18009
  function createSubagentExtension(prepare, discard, guard) {
17975
18010
  const finish = async (tx, input, status, report) => {
17976
18011
  const round = (await tx.doc(DelegationsDoc, input.parentId)).items.find((r) => r.taskId === input.taskId);
@@ -18004,7 +18039,7 @@ function createSubagentExtension(prepare, discard, guard) {
18004
18039
  return { status: "running", checkpoint: { phase: "deliver" } };
18005
18040
  }, ctx);
18006
18041
  if (!admitted)
18007
- await runtime.sleep(runtime.now() + 100, ctx);
18042
+ await pause(runtime, ADMISSION_POLL_MS);
18008
18043
  }
18009
18044
  },
18010
18045
  deliver: async (task, runtime, ctx) => {
@@ -18941,6 +18976,7 @@ var JOB_LIMITS = {
18941
18976
  };
18942
18977
  var JobsDoc = defineDoc3({
18943
18978
  kind: "app.neko.jobs",
18979
+ checkpointWhen: () => false,
18944
18980
  version: 1,
18945
18981
  scope: "conversation",
18946
18982
  history: "latest",
@@ -19075,6 +19111,7 @@ import { join as join5 } from "path";
19075
19111
  import { BACKGROUND_CONTEXT as BACKGROUND_CONTEXT3 } from "@earendil-works/chord/context";
19076
19112
  import { clampThinkingLevel, createModels, getSupportedThinkingLevels as getSupportedThinkingLevels2 } from "@earendil-works/pi-ai/models";
19077
19113
  import { builtinProviders } from "@earendil-works/pi-ai/providers/all";
19114
+ import { PI_ATTRIBUTION } from "@earendil-works/pi-ai/utils/identity";
19078
19115
  import {
19079
19116
  AssistantEntry as AssistantEntry2,
19080
19117
  createRegistry,
@@ -20010,6 +20047,7 @@ import {
20010
20047
  import { Type as Type4 } from "typebox";
20011
20048
  var QuestionDoc = defineDocFamily({
20012
20049
  kind: "app.neko.question",
20050
+ checkpointWhen: () => false,
20013
20051
  version: 1,
20014
20052
  scope: "conversation",
20015
20053
  history: "latest",
@@ -20019,6 +20057,7 @@ var QuestionDoc = defineDocFamily({
20019
20057
  });
20020
20058
  var QuestionsDoc = defineDoc4({
20021
20059
  kind: "app.neko.questions",
20060
+ checkpointWhen: () => false,
20022
20061
  version: 1,
20023
20062
  scope: "conversation",
20024
20063
  history: "latest",
@@ -20986,6 +21025,7 @@ import {
20986
21025
  } from "@earendil-works/pi-durable";
20987
21026
  var SessionMetadataDoc = defineDoc5({
20988
21027
  kind: "app.neko.session-metadata",
21028
+ checkpointWhen: () => false,
20989
21029
  version: 1,
20990
21030
  scope: "conversation",
20991
21031
  history: "latest",
@@ -21054,10 +21094,7 @@ function namingTask(canUse, { requestTimeoutMs, retryDelayMs }) {
21054
21094
  version: 1,
21055
21095
  initial: () => ({ phase: "wait", until: Date.now() + 100 }),
21056
21096
  phases: {
21057
- async wait(task, runtime, context) {
21058
- await runtime.sleep(task.state.checkpoint.until, context);
21059
- await runtime.commit(() => ({ status: "running", checkpoint: { phase: "generate", attempt: 0 } }), context);
21060
- },
21097
+ wait: (task, runtime, context) => runtime.sleepUntil(task.state.checkpoint.until, { phase: "generate", attempt: 0 }, context),
21061
21098
  async generate(_task, runtime, context) {
21062
21099
  while (active >= 2) {
21063
21100
  await new Promise((resolve, reject) => {
@@ -21327,6 +21364,7 @@ import { defineDoc as defineDoc6, defineExtension as defineExtension9, defineToo
21327
21364
  import { Type as Type6 } from "typebox";
21328
21365
  var TodosDoc = defineDoc6({
21329
21366
  kind: "app.neko.todos",
21367
+ checkpointWhen: () => false,
21330
21368
  version: 1,
21331
21369
  scope: "conversation",
21332
21370
  history: "rewindable",
@@ -21335,6 +21373,7 @@ var TodosDoc = defineDoc6({
21335
21373
  });
21336
21374
  var TodoReceiptDoc = defineDoc6({
21337
21375
  kind: "app.neko.todo-receipt",
21376
+ checkpointWhen: () => false,
21338
21377
  version: 1,
21339
21378
  scope: "task",
21340
21379
  initial: () => ({ applied: false, revision: 0, items: [] })
@@ -21433,6 +21472,7 @@ import {
21433
21472
  import { createBashTool as createBashTool2 } from "@earendil-works/pi-durable/tools";
21434
21473
  var ApprovalsDoc = defineDoc7({
21435
21474
  kind: "app.neko.approvals",
21475
+ checkpointWhen: () => false,
21436
21476
  version: 1,
21437
21477
  scope: "conversation",
21438
21478
  history: "latest",
@@ -22607,6 +22647,7 @@ var DEFAULT_STORAGE_PATH = join5(homedir4(), ".neko", "neko.sqlite");
22607
22647
  var neverAborted = () => new AbortController().signal;
22608
22648
  var ArchivedDoc = defineDoc8({
22609
22649
  kind: "app.neko.conversation",
22650
+ checkpointWhen: () => false,
22610
22651
  version: 1,
22611
22652
  scope: "conversation",
22612
22653
  history: "latest",
@@ -22615,6 +22656,7 @@ var ArchivedDoc = defineDoc8({
22615
22656
  });
22616
22657
  var WorkspacesDoc = defineDoc8({
22617
22658
  kind: "app.neko.workspaces",
22659
+ checkpointWhen: () => false,
22618
22660
  version: 1,
22619
22661
  scope: "conversation",
22620
22662
  history: "latest",
@@ -22623,6 +22665,7 @@ var WorkspacesDoc = defineDoc8({
22623
22665
  });
22624
22666
  var RemovedWorkspacesDoc = defineDoc8({
22625
22667
  kind: "app.neko.workspaces-removed",
22668
+ checkpointWhen: () => false,
22626
22669
  version: 1,
22627
22670
  scope: "conversation",
22628
22671
  history: "latest",
@@ -22631,6 +22674,7 @@ var RemovedWorkspacesDoc = defineDoc8({
22631
22674
  });
22632
22675
  var SearchSettingsDoc = defineDoc8({
22633
22676
  kind: "app.neko.search-settings",
22677
+ checkpointWhen: () => false,
22634
22678
  version: 1,
22635
22679
  scope: "conversation",
22636
22680
  history: "latest",
@@ -22639,6 +22683,7 @@ var SearchSettingsDoc = defineDoc8({
22639
22683
  });
22640
22684
  var ProviderSettingsDoc = defineDoc8({
22641
22685
  kind: "app.neko.provider-settings",
22686
+ checkpointWhen: () => false,
22642
22687
  version: 1,
22643
22688
  scope: "conversation",
22644
22689
  history: "latest",
@@ -22647,6 +22692,7 @@ var ProviderSettingsDoc = defineDoc8({
22647
22692
  });
22648
22693
  var DefaultModelDoc = defineDoc8({
22649
22694
  kind: "app.neko.default-model",
22695
+ checkpointWhen: () => false,
22650
22696
  version: 1,
22651
22697
  scope: "conversation",
22652
22698
  history: "latest",
@@ -22655,6 +22701,7 @@ var DefaultModelDoc = defineDoc8({
22655
22701
  });
22656
22702
  var ContextSettingsDoc = defineDoc8({
22657
22703
  kind: "app.neko.context-settings",
22704
+ checkpointWhen: () => false,
22658
22705
  version: 1,
22659
22706
  scope: "conversation",
22660
22707
  history: "latest",
@@ -22663,6 +22710,7 @@ var ContextSettingsDoc = defineDoc8({
22663
22710
  });
22664
22711
  var ActivityDoc = defineDoc8({
22665
22712
  kind: "app.neko.activity",
22713
+ checkpointWhen: () => false,
22666
22714
  version: 1,
22667
22715
  scope: "conversation",
22668
22716
  history: "latest",
@@ -22774,13 +22822,15 @@ async function createNekoRuntime(options = {}) {
22774
22822
  registry.install(approvalExtension);
22775
22823
  let savedContext = emptySavedContextSettings();
22776
22824
  let contextState = resolveContextSettings(options.contextSettings, savedContext);
22825
+ const compactionFor = createCompactionPolicy(new Map(allModels().map((model) => [`${model.provider}/${model.modelId}`, model.contextWindow])));
22777
22826
  const harness = await Harness.open(storage, {
22778
22827
  models,
22828
+ identity: { userAgent: "detailed", attribution: PI_ATTRIBUTION },
22779
22829
  registry,
22780
22830
  settings: {
22781
22831
  ...options.timings?.retryBaseDelayMs === undefined ? {} : { retry: { baseDelayMs: options.timings.retryBaseDelayMs } },
22782
22832
  get compaction() {
22783
- return compactionPolicy(contextState, allModels().filter((model) => !isModelProvider(model.provider) || enabled.has(model.provider)).map((model) => model.contextWindow));
22833
+ return compactionFor(contextState);
22784
22834
  }
22785
22835
  },
22786
22836
  onReport: options.onReport,
@@ -25040,7 +25090,7 @@ function subagentClient(connect) {
25040
25090
  import { createHash as createHash2 } from "crypto";
25041
25091
 
25042
25092
  // packages/core/src/application-version.ts
25043
- var RUNNING_VERSION = "0.5.0";
25093
+ var RUNNING_VERSION = "0.5.2";
25044
25094
  var APPLICATION_PROTOCOL = 9;
25045
25095
  function stableVersion(value) {
25046
25096
  return typeof value === "string" && /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.test(value) && value.split(".").every((n) => Number.isSafeInteger(Number(n)));
package/dist/neko.js CHANGED
@@ -80,7 +80,7 @@ function updateAction(input) {
80
80
  return "install";
81
81
  return "none";
82
82
  }
83
- var RUNNING_VERSION = "0.5.0", APPLICATION_PROTOCOL = 9, ApplicationProtocolError;
83
+ var RUNNING_VERSION = "0.5.2", APPLICATION_PROTOCOL = 9, ApplicationProtocolError;
84
84
  var init_application_version = __esm(() => {
85
85
  ApplicationProtocolError = class ApplicationProtocolError extends Error {
86
86
  constructor() {
@@ -556,11 +556,24 @@ function compactionPolicy(state, windows) {
556
556
  if (sources.compaction.keepRecentTokens !== "default")
557
557
  policy.keepRecentTokens = effective.compaction.keepRecentTokens;
558
558
  const percent = effective.compaction.triggerPercent;
559
- const window2 = windows.length > 0 ? Math.min(...windows) : 0;
560
- if (percent !== null && window2 > 0)
561
- policy.reserveTokens = window2 - Math.floor(window2 * percent / 100);
559
+ if (percent === null)
560
+ return policy;
561
+ const overrides = {};
562
+ for (const [id, window2] of windows)
563
+ if (window2 > 0)
564
+ overrides[id] = { reserveTokens: window2 - Math.floor(window2 * percent / 100) };
565
+ if (Object.keys(overrides).length > 0)
566
+ policy.modelOverrides = overrides;
562
567
  return policy;
563
568
  }
569
+ function createCompactionPolicy(windows) {
570
+ let last;
571
+ return (state) => {
572
+ if (last?.state !== state)
573
+ last = { state, policy: compactionPolicy(state, windows) };
574
+ return last.policy;
575
+ };
576
+ }
564
577
  var emptySavedContextSettings = () => ({
565
578
  compaction: { enabled: null, triggerPercent: null, keepRecentTokens: null },
566
579
  pruning: { enabled: null, triggerPercent: null, keepRecent: null, minChars: null, minSavePercent: null }
@@ -1512,6 +1525,7 @@ var PLAN_HISTORY = 5, PlanDoc, PLAN_CODER_BLOCKED = "Plan mode is read-only: the
1512
1525
  var init_plan_doc = __esm(() => {
1513
1526
  PlanDoc = defineDoc({
1514
1527
  kind: "app.neko.plan",
1528
+ checkpointWhen: () => false,
1515
1529
  version: 1,
1516
1530
  scope: "conversation",
1517
1531
  history: "rewindable",
@@ -1669,6 +1683,22 @@ async function acquireSlot(tx, round, cwd) {
1669
1683
  slots.items.push({ taskId: round.taskId, parentId: round.parentId, cwd, coder: round.role === "coder" });
1670
1684
  return true;
1671
1685
  }
1686
+ function pause(runtime, ms) {
1687
+ const { signal } = runtime;
1688
+ return new Promise((resolve, reject) => {
1689
+ if (signal.aborted)
1690
+ return reject(signal.reason);
1691
+ const disarm = runtime.setTimer(() => {
1692
+ signal.removeEventListener("abort", abort);
1693
+ resolve();
1694
+ }, ms);
1695
+ const abort = () => {
1696
+ disarm();
1697
+ reject(signal.reason);
1698
+ };
1699
+ signal.addEventListener("abort", abort, { once: true });
1700
+ });
1701
+ }
1672
1702
  function createSubagentExtension(prepare, discard, guard) {
1673
1703
  const finish = async (tx, input, status, report) => {
1674
1704
  const round = (await tx.doc(DelegationsDoc, input.parentId)).items.find((r) => r.taskId === input.taskId);
@@ -1702,7 +1732,7 @@ function createSubagentExtension(prepare, discard, guard) {
1702
1732
  return { status: "running", checkpoint: { phase: "deliver" } };
1703
1733
  }, ctx);
1704
1734
  if (!admitted)
1705
- await runtime.sleep(runtime.now() + 100, ctx);
1735
+ await pause(runtime, ADMISSION_POLL_MS);
1706
1736
  }
1707
1737
  },
1708
1738
  deliver: async (task, runtime, ctx) => {
@@ -1999,13 +2029,14 @@ async function installSubagentCoordinator(harness, parents, context) {
1999
2029
  });
2000
2030
  harness.closed.finally(stop).catch(() => {});
2001
2031
  }
2002
- var agentIdFor = (childId) => `agent-${childId}`, DelegationsDoc, SubagentsDoc, SubagentDoc, SlotsDoc, ROLE_PROMPTS, SUBAGENT_DELIVERY = " Work from the assigned task, your own prior conversation context and project resources; you cannot see the main conversation. Do not delegate or ask the user directly. Your final message must be a self-contained delivery to the main agent, including evidence, results and limitations. Skills never expand your allowed tools.", MAIN_ONLY_TOOLS, MAIN_ONLY_EXTENSIONS, READ_TOOLS, actionParameters, parameters, structuredOutputSchema;
2032
+ var agentIdFor = (childId) => `agent-${childId}`, DelegationsDoc, SubagentsDoc, SubagentDoc, SlotsDoc, ROLE_PROMPTS, SUBAGENT_DELIVERY = " Work from the assigned task, your own prior conversation context and project resources; you cannot see the main conversation. Do not delegate or ask the user directly. Your final message must be a self-contained delivery to the main agent, including evidence, results and limitations. Skills never expand your allowed tools.", MAIN_ONLY_TOOLS, MAIN_ONLY_EXTENSIONS, READ_TOOLS, actionParameters, parameters, structuredOutputSchema, ADMISSION_POLL_MS = 100;
2003
2033
  var init_subagents = __esm(() => {
2004
2034
  init_input();
2005
2035
  init_plan_doc();
2006
2036
  init_subagent_usage();
2007
2037
  DelegationsDoc = defineDoc2({
2008
2038
  kind: "app.neko.delegations",
2039
+ checkpointWhen: () => false,
2009
2040
  version: 1,
2010
2041
  scope: "conversation",
2011
2042
  history: "latest",
@@ -2014,6 +2045,7 @@ var init_subagents = __esm(() => {
2014
2045
  });
2015
2046
  SubagentsDoc = defineDoc2({
2016
2047
  kind: "app.neko.subagents",
2048
+ checkpointWhen: () => false,
2017
2049
  version: 1,
2018
2050
  scope: "conversation",
2019
2051
  history: "latest",
@@ -2022,6 +2054,7 @@ var init_subagents = __esm(() => {
2022
2054
  });
2023
2055
  SubagentDoc = defineDoc2({
2024
2056
  kind: "app.neko.subagent",
2057
+ checkpointWhen: () => false,
2025
2058
  version: 1,
2026
2059
  scope: "conversation",
2027
2060
  history: "latest",
@@ -2030,6 +2063,7 @@ var init_subagents = __esm(() => {
2030
2063
  });
2031
2064
  SlotsDoc = defineDoc2({
2032
2065
  kind: "app.neko.subagent-slots",
2066
+ checkpointWhen: () => false,
2033
2067
  version: 1,
2034
2068
  scope: "session",
2035
2069
  initial: () => ({ items: [] })
@@ -2878,6 +2912,7 @@ var init_jobs = __esm(() => {
2878
2912
  };
2879
2913
  JobsDoc = defineDoc3({
2880
2914
  kind: "app.neko.jobs",
2915
+ checkpointWhen: () => false,
2881
2916
  version: 1,
2882
2917
  scope: "conversation",
2883
2918
  history: "latest",
@@ -4103,6 +4138,7 @@ var init_user_questions = __esm(() => {
4103
4138
  init_subagents();
4104
4139
  QuestionDoc = defineDocFamily({
4105
4140
  kind: "app.neko.question",
4141
+ checkpointWhen: () => false,
4106
4142
  version: 1,
4107
4143
  scope: "conversation",
4108
4144
  history: "latest",
@@ -4112,6 +4148,7 @@ var init_user_questions = __esm(() => {
4112
4148
  });
4113
4149
  QuestionsDoc = defineDoc4({
4114
4150
  kind: "app.neko.questions",
4151
+ checkpointWhen: () => false,
4115
4152
  version: 1,
4116
4153
  scope: "conversation",
4117
4154
  history: "latest",
@@ -4855,10 +4892,7 @@ function namingTask(canUse, { requestTimeoutMs, retryDelayMs }) {
4855
4892
  version: 1,
4856
4893
  initial: () => ({ phase: "wait", until: Date.now() + 100 }),
4857
4894
  phases: {
4858
- async wait(task, runtime, context) {
4859
- await runtime.sleep(task.state.checkpoint.until, context);
4860
- await runtime.commit(() => ({ status: "running", checkpoint: { phase: "generate", attempt: 0 } }), context);
4861
- },
4895
+ wait: (task, runtime, context) => runtime.sleepUntil(task.state.checkpoint.until, { phase: "generate", attempt: 0 }, context),
4862
4896
  async generate(_task, runtime, context) {
4863
4897
  while (active >= 2) {
4864
4898
  await new Promise((resolve, reject) => {
@@ -5129,6 +5163,7 @@ var init_session_metadata = __esm(() => {
5129
5163
  init_user_questions();
5130
5164
  SessionMetadataDoc = defineDoc5({
5131
5165
  kind: "app.neko.session-metadata",
5166
+ checkpointWhen: () => false,
5132
5167
  version: 1,
5133
5168
  scope: "conversation",
5134
5169
  history: "latest",
@@ -5221,6 +5256,7 @@ var init_todos = __esm(() => {
5221
5256
  init_subagents();
5222
5257
  TodosDoc = defineDoc6({
5223
5258
  kind: "app.neko.todos",
5259
+ checkpointWhen: () => false,
5224
5260
  version: 1,
5225
5261
  scope: "conversation",
5226
5262
  history: "rewindable",
@@ -5229,6 +5265,7 @@ var init_todos = __esm(() => {
5229
5265
  });
5230
5266
  TodoReceiptDoc = defineDoc6({
5231
5267
  kind: "app.neko.todo-receipt",
5268
+ checkpointWhen: () => false,
5232
5269
  version: 1,
5233
5270
  scope: "task",
5234
5271
  initial: () => ({ applied: false, revision: 0, items: [] })
@@ -5431,6 +5468,7 @@ var init_tool_approvals = __esm(() => {
5431
5468
  init_subagents();
5432
5469
  ApprovalsDoc = defineDoc7({
5433
5470
  kind: "app.neko.approvals",
5471
+ checkpointWhen: () => false,
5434
5472
  version: 1,
5435
5473
  scope: "conversation",
5436
5474
  history: "latest",
@@ -6447,6 +6485,7 @@ import { join as join7 } from "path";
6447
6485
  import { BACKGROUND_CONTEXT as BACKGROUND_CONTEXT3 } from "@earendil-works/chord/context";
6448
6486
  import { clampThinkingLevel, createModels, getSupportedThinkingLevels as getSupportedThinkingLevels2 } from "@earendil-works/pi-ai/models";
6449
6487
  import { builtinProviders } from "@earendil-works/pi-ai/providers/all";
6488
+ import { PI_ATTRIBUTION } from "@earendil-works/pi-ai/utils/identity";
6450
6489
  import {
6451
6490
  AssistantEntry as AssistantEntry2,
6452
6491
  createRegistry,
@@ -6566,13 +6605,15 @@ async function createNekoRuntime(options = {}) {
6566
6605
  registry.install(approvalExtension);
6567
6606
  let savedContext = emptySavedContextSettings();
6568
6607
  let contextState = resolveContextSettings(options.contextSettings, savedContext);
6608
+ const compactionFor = createCompactionPolicy(new Map(allModels().map((model) => [`${model.provider}/${model.modelId}`, model.contextWindow])));
6569
6609
  const harness = await Harness.open(storage, {
6570
6610
  models,
6611
+ identity: { userAgent: "detailed", attribution: PI_ATTRIBUTION },
6571
6612
  registry,
6572
6613
  settings: {
6573
6614
  ...options.timings?.retryBaseDelayMs === undefined ? {} : { retry: { baseDelayMs: options.timings.retryBaseDelayMs } },
6574
6615
  get compaction() {
6575
- return compactionPolicy(contextState, allModels().filter((model) => !isModelProvider(model.provider) || enabled.has(model.provider)).map((model) => model.contextWindow));
6616
+ return compactionFor(contextState);
6576
6617
  }
6577
6618
  },
6578
6619
  onReport: options.onReport,
@@ -7432,6 +7473,7 @@ var init_runtime = __esm(() => {
7432
7473
  DEFAULT_STORAGE_PATH = join7(homedir5(), ".neko", "neko.sqlite");
7433
7474
  ArchivedDoc = defineDoc8({
7434
7475
  kind: "app.neko.conversation",
7476
+ checkpointWhen: () => false,
7435
7477
  version: 1,
7436
7478
  scope: "conversation",
7437
7479
  history: "latest",
@@ -7440,6 +7482,7 @@ var init_runtime = __esm(() => {
7440
7482
  });
7441
7483
  WorkspacesDoc = defineDoc8({
7442
7484
  kind: "app.neko.workspaces",
7485
+ checkpointWhen: () => false,
7443
7486
  version: 1,
7444
7487
  scope: "conversation",
7445
7488
  history: "latest",
@@ -7448,6 +7491,7 @@ var init_runtime = __esm(() => {
7448
7491
  });
7449
7492
  RemovedWorkspacesDoc = defineDoc8({
7450
7493
  kind: "app.neko.workspaces-removed",
7494
+ checkpointWhen: () => false,
7451
7495
  version: 1,
7452
7496
  scope: "conversation",
7453
7497
  history: "latest",
@@ -7456,6 +7500,7 @@ var init_runtime = __esm(() => {
7456
7500
  });
7457
7501
  SearchSettingsDoc = defineDoc8({
7458
7502
  kind: "app.neko.search-settings",
7503
+ checkpointWhen: () => false,
7459
7504
  version: 1,
7460
7505
  scope: "conversation",
7461
7506
  history: "latest",
@@ -7464,6 +7509,7 @@ var init_runtime = __esm(() => {
7464
7509
  });
7465
7510
  ProviderSettingsDoc = defineDoc8({
7466
7511
  kind: "app.neko.provider-settings",
7512
+ checkpointWhen: () => false,
7467
7513
  version: 1,
7468
7514
  scope: "conversation",
7469
7515
  history: "latest",
@@ -7472,6 +7518,7 @@ var init_runtime = __esm(() => {
7472
7518
  });
7473
7519
  DefaultModelDoc = defineDoc8({
7474
7520
  kind: "app.neko.default-model",
7521
+ checkpointWhen: () => false,
7475
7522
  version: 1,
7476
7523
  scope: "conversation",
7477
7524
  history: "latest",
@@ -7480,6 +7527,7 @@ var init_runtime = __esm(() => {
7480
7527
  });
7481
7528
  ContextSettingsDoc = defineDoc8({
7482
7529
  kind: "app.neko.context-settings",
7530
+ checkpointWhen: () => false,
7483
7531
  version: 1,
7484
7532
  scope: "conversation",
7485
7533
  history: "latest",
@@ -7488,6 +7536,7 @@ var init_runtime = __esm(() => {
7488
7536
  });
7489
7537
  ActivityDoc = defineDoc8({
7490
7538
  kind: "app.neko.activity",
7539
+ checkpointWhen: () => false,
7491
7540
  version: 1,
7492
7541
  scope: "conversation",
7493
7542
  history: "latest",
@@ -32248,7 +32297,7 @@ var init_en = __esm(() => {
32248
32297
  "context.row.autoCompaction.label": "Auto compaction",
32249
32298
  "context.row.autoCompaction.description": "Compact automatically near the limit. /compact always works.",
32250
32299
  "context.row.compactAt.label": "Compact at",
32251
- "context.row.compactAt.description": "Compact when context reaches this share of the smallest model window. Default is near the limit.",
32300
+ "context.row.compactAt.description": "Compact when context reaches this share of the current model's window. Default is near the limit.",
32252
32301
  "context.row.keepRecent.label": "Keep recent",
32253
32302
  "context.row.keepRecent.description": "Recent context a compaction keeps verbatim.",
32254
32303
  "context.row.pruneResults.label": "Prune tool results",
@@ -32869,7 +32918,7 @@ var init_zh = __esm(() => {
32869
32918
  "context.row.autoCompaction.label": "\u81EA\u52A8\u538B\u7F29",
32870
32919
  "context.row.autoCompaction.description": "\u63A5\u8FD1\u4E0A\u9650\u65F6\u81EA\u52A8\u538B\u7F29\u3002/compact \u59CB\u7EC8\u53EF\u7528\u3002",
32871
32920
  "context.row.compactAt.label": "\u538B\u7F29\u9608\u503C",
32872
- "context.row.compactAt.description": "\u4E0A\u4E0B\u6587\u8FBE\u5230\u6700\u5C0F\u6A21\u578B\u7A97\u53E3\u7684\u6B64\u6BD4\u4F8B\u65F6\u538B\u7F29\u3002\u9ED8\u8BA4\u63A5\u8FD1\u4E0A\u9650\u3002",
32921
+ "context.row.compactAt.description": "\u4E0A\u4E0B\u6587\u8FBE\u5230\u5F53\u524D\u6A21\u578B\u7A97\u53E3\u7684\u6B64\u6BD4\u4F8B\u65F6\u538B\u7F29\u3002\u9ED8\u8BA4\u63A5\u8FD1\u4E0A\u9650\u3002",
32873
32922
  "context.row.keepRecent.label": "\u4FDD\u7559\u6700\u8FD1\u5185\u5BB9",
32874
32923
  "context.row.keepRecent.description": "\u538B\u7F29\u65F6\u539F\u6837\u4FDD\u7559\u7684\u6700\u8FD1\u4E0A\u4E0B\u6587\u3002",
32875
32924
  "context.row.pruneResults.label": "\u88C1\u526A\u5DE5\u5177\u7ED3\u679C",
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "packages/*"
6
6
  ],
7
7
  "engines": {
8
- "bun": ">=1.4.2 <1.5.0"
8
+ "bun": ">=1.4.0 <1.5.0"
9
9
  },
10
10
  "scripts": {
11
11
  "build": "bun run --cwd packages/core build && bun run --cwd packages/gateway build && bun run --cwd packages/tui build && bun run --cwd packages/web build && bun run --cwd packages/cli build",
@@ -19,14 +19,14 @@
19
19
  },
20
20
  "devDependencies": {
21
21
  "@biomejs/biome": "2.3.5",
22
- "@types/bun": "1.4.2",
22
+ "@types/bun": "1.4.3",
23
23
  "@types/node": "22.20.5",
24
24
  "qrcode-generator": "2.0.4",
25
25
  "typescript": "7.0.2"
26
26
  },
27
- "packageManager": "bun@1.4.2",
27
+ "packageManager": "bun@1.4.4",
28
28
  "trustedDependencies": [],
29
- "version": "0.5.0",
29
+ "version": "0.5.2",
30
30
  "description": "A local AI coding assistant with terminal and web interfaces, powered by Pi and Bun.",
31
31
  "keywords": [
32
32
  "ai",
@@ -61,14 +61,14 @@
61
61
  "registry": "https://registry.npmjs.org"
62
62
  },
63
63
  "dependencies": {
64
- "@earendil-works/chord": "1.3.0",
65
- "@earendil-works/pi-ai": "1.3.0",
66
- "@earendil-works/pi-durable": "1.3.0",
67
- "@earendil-works/pi-tui": "1.3.0",
64
+ "@earendil-works/chord": "1.4.0",
65
+ "@earendil-works/pi-ai": "1.4.0",
66
+ "@earendil-works/pi-durable": "1.4.0",
67
+ "@earendil-works/pi-tui": "1.4.0",
68
68
  "sharp": "0.35.5",
69
69
  "ws": "8.22.0",
70
70
  "yaml": "2.9.1",
71
- "@earendil-works/pi-env": "1.3.0",
71
+ "@earendil-works/pi-env": "1.4.0",
72
72
  "typebox": "1.3.27"
73
73
  }
74
74
  }