@code-yeongyu/senpi-agent-core 2026.10.30-2 → 2026.10.31-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.
@@ -431,6 +431,9 @@ export async function buildProviderContext(context, config, signal) {
431
431
  const { tools, activeToolNames } = providerTools(context, config.model);
432
432
  return normalizeContext({
433
433
  systemPrompt: context.systemPrompt,
434
+ ...(context.systemPromptStablePrefix === undefined
435
+ ? {}
436
+ : { systemPromptStablePrefix: context.systemPromptStablePrefix }),
434
437
  messages: await config.convertToLlm(messages),
435
438
  ...(tools === undefined ? {} : { tools: tools.map(toProviderToolDeclaration) }),
436
439
  ...(activeToolNames === undefined ? {} : { activeToolNames }),
package/dist/agent.js CHANGED
@@ -35,6 +35,7 @@ function createMutableAgentState(initialState) {
35
35
  let messages = initialState?.messages?.slice() ?? [];
36
36
  return {
37
37
  systemPrompt: initialState?.systemPrompt ?? "",
38
+ systemPromptStablePrefix: initialState?.systemPromptStablePrefix,
38
39
  model: initialState?.model ?? DEFAULT_MODEL,
39
40
  thinkingLevel: initialState?.thinkingLevel ?? "off",
40
41
  reasoningBaseline: initialState?.reasoningBaseline,
@@ -448,6 +449,9 @@ export class Agent {
448
449
  createContextSnapshot() {
449
450
  return {
450
451
  systemPrompt: this._state.systemPrompt,
452
+ ...(this._state.systemPromptStablePrefix === undefined
453
+ ? {}
454
+ : { systemPromptStablePrefix: this._state.systemPromptStablePrefix }),
451
455
  messages: this._state.messages.slice(),
452
456
  tools: this._state.tools.slice(),
453
457
  ...(this._state.declaredTools ? { declaredTools: this._state.declaredTools.slice() } : {}),
@@ -111,12 +111,15 @@ async function loadSkillsFromDirInternal(env, dir, includeRootFiles, ignoreMatch
111
111
  const kind = await resolveKind(env, entry, diagnostics, context);
112
112
  if (!kind)
113
113
  continue;
114
+ // A linked entry belongs to another tree: the ignore files above it neither hide it nor reach into it,
115
+ // while a linked directory's own ignore files still apply inside it (senpi#5060, senpi#5069).
116
+ const isLink = entry.kind === "symlink";
114
117
  const relPath = relativeEnvPath(rootDir, fullPath);
115
118
  const ignorePath = kind === "directory" ? `${relPath}/` : relPath;
116
- if (ignoreMatcher.ignores(ignorePath))
119
+ if (!isLink && ignoreMatcher.ignores(ignorePath))
117
120
  continue;
118
121
  if (kind === "directory") {
119
- const result = await loadSkillsFromDirInternal(env, fullPath, false, ignoreMatcher, rootDir, context);
122
+ const result = await loadSkillsFromDirInternal(env, fullPath, false, isLink ? ignore() : ignoreMatcher, rootDir, context);
120
123
  skills.push(...result.skills);
121
124
  diagnostics.push(...result.diagnostics);
122
125
  continue;
package/dist/types.d.ts CHANGED
@@ -398,6 +398,11 @@ export interface AgentState {
398
398
  * `content` or `sections` still apply on top of it.
399
399
  */
400
400
  systemPrompt: string;
401
+ /**
402
+ * Leading part of `systemPrompt` that is the same across sessions; see
403
+ * {@link AgentContext.systemPromptStablePrefix} (senpi#4447).
404
+ */
405
+ systemPromptStablePrefix?: string;
401
406
  /** Active model used for future turns. */
402
407
  model: Model<any>;
403
408
  /** Requested reasoning level for future turns. */
@@ -520,6 +525,13 @@ export interface AgentContext {
520
525
  * `normalizeContext()`. Upstream-built contexts carry the prompt in transcript system messages.
521
526
  */
522
527
  systemPrompt?: string;
528
+ /**
529
+ * Leading part of `systemPrompt` that is the same across sessions, followed by content that is not
530
+ * (memory, MCP instructions). Providers with block-level prompt caching put the system breakpoint at
531
+ * its end so another session can read it from cache. Ignored unless `systemPrompt` starts with it
532
+ * (senpi#4447).
533
+ */
534
+ systemPromptStablePrefix?: string;
523
535
  /** Transcript visible to the model. */
524
536
  messages: AgentMessage[];
525
537
  /** Tools available for execution in this run. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/senpi-agent-core",
3
- "version": "2026.10.30-2",
3
+ "version": "2026.10.31-1",
4
4
  "description": "General-purpose agent with transport abstraction, state management, and attachment support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -70,8 +70,8 @@
70
70
  },
71
71
  "dependencies": {
72
72
  "@earendil-works/chord": "0.99.1",
73
- "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.10.30-2",
74
- "@earendil-works/pi-telemetry": "npm:@code-yeongyu/senpi-telemetry@2026.10.30-2",
73
+ "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.10.31-1",
74
+ "@earendil-works/pi-telemetry": "npm:@code-yeongyu/senpi-telemetry@2026.10.31-1",
75
75
  "diff": "9.0.0",
76
76
  "ignore": "7.0.9",
77
77
  "typebox": "1.3.34",