@oh-my-pi/pi-coding-agent 16.0.3 → 16.0.4

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/src/main.ts CHANGED
@@ -124,11 +124,9 @@ async function checkForNewVersion(currentVersion: string): Promise<string | unde
124
124
  }
125
125
  }
126
126
 
127
+ // Todo settings are caller-controlled in protocol modes. Do not host-default them:
128
+ // embedders need project-level opt-outs for reminder/prelude prompt injection.
127
129
  const HOST_DEFAULTED_SETTING_PATHS: SettingPath[] = [
128
- "todo.enabled",
129
- "todo.reminders",
130
- "todo.reminders.max",
131
- "todo.eager",
132
130
  "task.isolation.mode",
133
131
  "task.isolation.merge",
134
132
  "task.isolation.commits",
@@ -1041,6 +1039,10 @@ export async function runRootCommand(
1041
1039
  if (parsedArgs.hideThinking) {
1042
1040
  settingsInstance.override("hideThinkingBlock", true);
1043
1041
  }
1042
+ // Apply --advisor CLI flag (ephemeral, not persisted)
1043
+ if (parsedArgs.advisor) {
1044
+ settingsInstance.override("advisor.enabled", true);
1045
+ }
1044
1046
 
1045
1047
  await logger.time(
1046
1048
  "initTheme:final",
@@ -19,4 +19,5 @@ Press ctrl+r to search your prompt history and reuse a past message
19
19
  `/shake` rips heavy tool results out of context to reclaim tokens without a full /compact — `/shake images` drops just images
20
20
  Pair up live: `/collab` shares your session through an end-to-end encrypted relay link — a teammate runs `/join <link>` to watch tool calls stream and prompt the agent from their own omp
21
21
  Press ← ← to drill into a running or finished agent and inspect its tool calls and transcript
22
- Hit a Codex rate limit? `/usage reset` spends a saved reset credit to immediately restore your quota
22
+ Hit a Codex rate limit? `/usage reset` spends a saved reset credit to immediately restore your quota
23
+ No native tool_calling? Inference provider botches parsing them? `PI_DIALECT=glm|kimi|anthropic…` rolls it locally for them!
@@ -117,6 +117,8 @@ ENV
117
117
 
118
118
  # Skills & Rules
119
119
  {{#if skills.length}}
120
+ Skills are specialized knowledge. Scan descriptions for your task domain.
121
+ If a skill applies, you MUST read `skill://<name>` before proceeding.
120
122
  <skills>
121
123
  {{#each skills}}
122
124
  - {{name}}: {{description}}
@@ -8164,14 +8164,17 @@ export class AgentSession {
8164
8164
  maxAttempts: remindersMax,
8165
8165
  });
8166
8166
 
8167
- this.#todoReminderAwaitingProgress = true;
8168
- // Inject reminder and continue the conversation
8169
- this.agent.appendMessage({
8167
+ const reminderMessage: Message = {
8170
8168
  role: "developer",
8171
8169
  content: [{ type: "text", text: reminder }],
8172
8170
  attribution: "agent",
8173
8171
  timestamp: Date.now(),
8174
- });
8172
+ };
8173
+
8174
+ this.#todoReminderAwaitingProgress = true;
8175
+ // Inject reminder and persist it so the JSONL transcript matches model context.
8176
+ this.agent.appendMessage(reminderMessage);
8177
+ this.sessionManager.appendMessage(reminderMessage);
8175
8178
  this.#scheduleAgentContinue({ generation: this.#promptGeneration });
8176
8179
  }
8177
8180
 
package/src/tools/read.ts CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  canonicalSnapshotKey,
15
15
  getFileSnapshotStore,
16
16
  recordFileSnapshot,
17
+ recordSeenLines,
17
18
  recordSeenLinesFromBody,
18
19
  SNAPSHOT_MAX_BYTES,
19
20
  } from "../edit/file-snapshot-store";
@@ -288,6 +289,20 @@ function countTextLines(text: string): number {
288
289
  return text.split("\n").length;
289
290
  }
290
291
 
292
+ function contiguousLineNumbers(startLine: number, count: number): number[] {
293
+ const lines: number[] = [];
294
+ for (let offset = 0; offset < count; offset++) lines.push(startLine + offset);
295
+ return lines;
296
+ }
297
+
298
+ function lineNumbersFromEntries(entries: readonly LineEntry[]): number[] {
299
+ const lines: number[] = [];
300
+ for (const entry of entries) {
301
+ if (entry.kind === "line") lines.push(entry.lineNumber);
302
+ }
303
+ return lines;
304
+ }
305
+
291
306
  /** Inclusive line range describing one elided span in a structural summary. */
292
307
  interface ElidedRange {
293
308
  start: number;
@@ -1041,8 +1056,10 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1041
1056
  )
1042
1057
  : undefined;
1043
1058
  let emittedHashlineHeader = false;
1059
+ let seenLines: number[] | undefined;
1044
1060
  const formatText = (content: string, startNum: number): string => {
1045
1061
  details.displayContent = { text: content, startLine: startNum };
1062
+ if (shouldAddHashLines) seenLines = contiguousLineNumbers(startNum, countTextLines(content));
1046
1063
  const formatted = formatTextWithMode(content, startNum, shouldAddHashLines, shouldAddLineNumbers);
1047
1064
  if (!hashContext || emittedHashlineHeader) return formatted;
1048
1065
  emittedHashlineHeader = true;
@@ -1054,6 +1071,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1054
1071
  text: lineEntriesToPlainText(entries, BRACKET_CONTEXT_ELLIPSIS),
1055
1072
  startLine: firstLine?.kind === "line" ? firstLine.lineNumber : startNum,
1056
1073
  };
1074
+ if (shouldAddHashLines) seenLines = lineNumbersFromEntries(entries);
1057
1075
  const formatted = formatLineEntriesWithMode(entries, shouldAddHashLines, shouldAddLineNumbers);
1058
1076
  if (!hashContext || emittedHashlineHeader) return formatted;
1059
1077
  emittedHashlineHeader = true;
@@ -1121,6 +1139,9 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1121
1139
  : formatLineEntries(buildLineEntries(endLine), startLineDisplay);
1122
1140
  }
1123
1141
 
1142
+ if (hashContext?.tag && options.sourcePath && seenLines) {
1143
+ recordSeenLines(this.session, options.sourcePath, hashContext.tag, seenLines);
1144
+ }
1124
1145
  resultBuilder.text(outputText);
1125
1146
  if (truncationInfo) {
1126
1147
  resultBuilder.truncation(truncationInfo.result, truncationInfo.options);
@@ -1165,6 +1186,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1165
1186
  : undefined;
1166
1187
  let emittedHashlineHeader = false;
1167
1188
 
1189
+ let seenLines: number[] | undefined;
1168
1190
  const resultBuilder = toolResult(details);
1169
1191
  if (options.sourcePath) resultBuilder.sourcePath(options.sourcePath);
1170
1192
  if (options.sourceUrl) resultBuilder.sourceUrl(options.sourceUrl);
@@ -1190,6 +1212,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1190
1212
  outputText = rawParts.length > 0 ? rawParts.join("\n\n…\n\n") : "";
1191
1213
  } else if (visibleSpans.length > 0) {
1192
1214
  const entries = buildLineEntriesWithBlockContext(allLines, visibleSpans, { path: options.sourcePath });
1215
+ if (shouldAddHashLines) seenLines = lineNumbersFromEntries(entries);
1193
1216
  const firstLine = entries.find(entry => entry.kind === "line");
1194
1217
  if (firstLine?.kind === "line") {
1195
1218
  details.displayContent = {
@@ -1208,6 +1231,9 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1208
1231
  }
1209
1232
  const finalText =
1210
1233
  notices.length > 0 ? (outputText ? `${outputText}\n${notices.join("\n")}` : notices.join("\n")) : outputText;
1234
+ if (hashContext?.tag && options.sourcePath && seenLines) {
1235
+ recordSeenLines(this.session, options.sourcePath, hashContext.tag, seenLines);
1236
+ }
1211
1237
  resultBuilder.text(finalText);
1212
1238
  return resultBuilder.done();
1213
1239
  }