@tekmidian/pai 0.44.0 → 0.46.0

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.
@@ -135,12 +135,13 @@ function findSessionNotes(notesDir) {
135
135
  function normalizeLine(line) {
136
136
  return line.replace(/^(- \[[ x]\] |- |\* |\d+\.\s)/, "").trim().replace(/\s+/g, " ");
137
137
  }
138
- function extractKeyLines(content, maxChars, seen = /* @__PURE__ */ new Set()) {
138
+ function extractKeyLines(content, maxChars, seen = /* @__PURE__ */ new Set(), seenLabels = /* @__PURE__ */ new Set()) {
139
139
  const lines = content.split("\n");
140
140
  const selected = [];
141
141
  let inTargetSection = false;
142
142
  let currentSection = "";
143
143
  let charCount = 0;
144
+ let pendingLabel = null;
144
145
  for (const line of lines) {
145
146
  const h2Match = line.match(/^## (.+)$/);
146
147
  const h3Match = line.match(/^### (.+)$/);
@@ -149,15 +150,12 @@ function extractKeyLines(content, maxChars, seen = /* @__PURE__ */ new Set()) {
149
150
  inTargetSection = EXTRACT_SECTIONS.some(
150
151
  (s) => currentSection.toLowerCase().includes(s.toLowerCase())
151
152
  );
153
+ pendingLabel = null;
152
154
  continue;
153
155
  }
154
156
  if (h3Match) {
155
157
  if (inTargetSection) {
156
- const label = `[${h3Match[1]}]`;
157
- if (charCount + label.length < maxChars) {
158
- selected.push(label);
159
- charCount += label.length + 1;
160
- }
158
+ pendingLabel = h3Match[1];
161
159
  }
162
160
  continue;
163
161
  }
@@ -167,7 +165,21 @@ function extractKeyLines(content, maxChars, seen = /* @__PURE__ */ new Set()) {
167
165
  if (trimmed.startsWith("- ") || trimmed.startsWith("* ") || trimmed.match(/^\d+\./) || trimmed.startsWith("**")) {
168
166
  const normalized = normalizeLine(trimmed);
169
167
  if (seen.has(normalized)) continue;
170
- if (charCount + trimmed.length + 1 > maxChars) break;
168
+ let labelText = "";
169
+ let labelKey = "";
170
+ if (pendingLabel !== null) {
171
+ labelKey = pendingLabel.toLowerCase().trim();
172
+ if (!seenLabels.has(labelKey)) {
173
+ labelText = `[${pendingLabel}]`;
174
+ }
175
+ }
176
+ if (charCount + labelText.length + trimmed.length + 2 > maxChars) break;
177
+ if (labelText) {
178
+ selected.push(labelText);
179
+ seenLabels.add(labelKey);
180
+ charCount += labelText.length + 1;
181
+ }
182
+ pendingLabel = null;
171
183
  seen.add(normalized);
172
184
  selected.push(trimmed);
173
185
  charCount += trimmed.length + 1;
@@ -183,6 +195,7 @@ function buildL1EssentialStory(rootPath, tokenBudget = L1_TOKEN_BUDGET) {
183
195
  if (noteFiles.length === 0) return "";
184
196
  const sections = [];
185
197
  const seen = /* @__PURE__ */ new Set();
198
+ const seenLabels = /* @__PURE__ */ new Set();
186
199
  let remaining = charBudget;
187
200
  for (const noteFile of noteFiles) {
188
201
  if (remaining <= 50) break;
@@ -197,8 +210,9 @@ function buildL1EssentialStory(rootPath, tokenBudget = L1_TOKEN_BUDGET) {
197
210
  const dateLabel = titleMatch ? titleMatch[1] : "";
198
211
  const titleLabel = titleMatch ? titleMatch[2] : name.replace(/^\d+ - /, "").replace(/\.md$/, "");
199
212
  const perNoteChars = Math.min(remaining, Math.floor(charBudget / noteFiles.length) + 200);
200
- const extracted = extractKeyLines(content, perNoteChars, seen);
201
- if (!extracted) continue;
213
+ const extracted = extractKeyLines(content, perNoteChars, seen, seenLabels);
214
+ const hasContentLine = extracted.split("\n").some((l) => !/^\[.*\]$/.test(l));
215
+ if (!extracted || !hasContentLine) continue;
202
216
  const noteBlock = `[${dateLabel} - ${titleLabel}]
203
217
  ${extracted}`;
204
218
  sections.push(noteBlock);
@@ -207,9 +221,9 @@ ${extracted}`;
207
221
  if (sections.length === 0) return "";
208
222
  return sections.join("\n\n");
209
223
  }
210
- function buildWakeupContext(rootPath, tokenBudget = L1_TOKEN_BUDGET) {
224
+ function buildWakeupContext(rootPath, tokenBudget = L1_TOKEN_BUDGET, opts = {}) {
211
225
  const identity = loadL0Identity();
212
- const essentialStory = rootPath ? buildL1EssentialStory(rootPath, tokenBudget) : "";
226
+ const essentialStory = rootPath && !opts.skipStory ? buildL1EssentialStory(rootPath, tokenBudget) : "";
213
227
  if (!identity && !essentialStory) return "";
214
228
  const parts = [];
215
229
  if (identity) {
@@ -1011,10 +1025,12 @@ Session Commands:
1011
1025
  </system-reminder>
1012
1026
  `;
1013
1027
  console.log(reminder);
1028
+ let handoverInjected = false;
1014
1029
  if (existsSync7(todoPath)) {
1015
1030
  try {
1016
1031
  const checkpoint = readContinueCheckpoint(readFileSync6(todoPath, "utf-8"));
1017
1032
  if (checkpoint) {
1033
+ handoverInjected = true;
1018
1034
  const from = checkpoint.meta?.session ? `
1019
1035
  From session: ${checkpoint.meta.session}` : "";
1020
1036
  const when = checkpoint.meta?.ts ? `
@@ -1073,7 +1089,7 @@ THE ABOVE INSTRUCTIONS ARE MANDATORY. Follow them exactly.
1073
1089
  } catch {
1074
1090
  wakeupRootPath = cwd;
1075
1091
  }
1076
- const wakeupBlock = buildWakeupContext(wakeupRootPath);
1092
+ const wakeupBlock = buildWakeupContext(wakeupRootPath, void 0, { skipStory: handoverInjected });
1077
1093
  if (wakeupBlock) {
1078
1094
  const wakeupReminder = `
1079
1095
  <system-reminder>