@howaboua/pi-codex-conversion 1.5.0 → 1.5.1-dev.13.d55bc98

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@howaboua/pi-codex-conversion",
3
- "version": "1.5.0",
3
+ "version": "1.5.1-dev.13.d55bc98",
4
4
  "description": "Codex-oriented tool and prompt adapter for pi coding agent",
5
5
  "type": "module",
6
6
  "repository": {
package/src/index.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
2
+ import { existsSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { join, resolve } from "node:path";
2
5
  import { getCodexRuntimeShell } from "./adapter/runtime-shell.ts";
3
6
  import {
4
7
  CORE_ADAPTER_TOOL_NAMES,
@@ -20,7 +23,7 @@ import {
20
23
  registerOpenAICodexCustomProvider,
21
24
  } from "./providers/openai-codex-custom-provider.ts";
22
25
  import { registerImageGenerationTool, rewriteNativeImageGenerationTool, supportsNativeImageGeneration } from "./tools/image-generation-tool.ts";
23
- import { buildCodexSystemPrompt, extractPiPromptSkills, type PromptSkill } from "./prompt/build-system-prompt.ts";
26
+ import { buildCodexSystemPrompt, extractPiPromptSkills, resolvePromptSkills, type PromptSkill } from "./prompt/build-system-prompt.ts";
24
27
  import { registerViewImageTool, supportsOriginalImageDetail } from "./tools/view-image-tool.ts";
25
28
  import {
26
29
  registerWebSearchTool,
@@ -83,6 +86,11 @@ export default function codexConversion(pi: ExtensionAPI) {
83
86
  syncAdapter(pi, ctx, state);
84
87
  });
85
88
 
89
+ pi.on("resources_discover", async (event) => {
90
+ const skillPaths = getCodexSkillPaths(event.cwd);
91
+ return skillPaths.length > 0 ? { skillPaths } : undefined;
92
+ });
93
+
86
94
  pi.on("model_select", async (_event, ctx) => {
87
95
  state.cwd = ctx.cwd;
88
96
  syncAdapter(pi, ctx, state);
@@ -118,9 +126,10 @@ export default function codexConversion(pi: ExtensionAPI) {
118
126
  if (!isCodexLikeContext(ctx)) {
119
127
  return undefined;
120
128
  }
129
+ const skills = resolvePromptSkills(event.systemPromptOptions?.skills, state.promptSkills);
121
130
  return {
122
131
  systemPrompt: buildCodexSystemPrompt(event.systemPrompt, {
123
- skills: state.promptSkills,
132
+ skills,
124
133
  shell: getCodexRuntimeShell(process.env.SHELL),
125
134
  }),
126
135
  };
@@ -149,6 +158,20 @@ export default function codexConversion(pi: ExtensionAPI) {
149
158
  });
150
159
  }
151
160
 
161
+ export function getCodexSkillPaths(cwd: string, home: string = homedir()): string[] {
162
+ const skillPaths = [join(home, ".agents", "skills")];
163
+ let currentDir = resolve(cwd);
164
+ while (true) {
165
+ skillPaths.push(join(currentDir, ".agents", "skills"));
166
+ const parentDir = resolve(currentDir, "..");
167
+ if (parentDir === currentDir) {
168
+ break;
169
+ }
170
+ currentDir = parentDir;
171
+ }
172
+ return skillPaths.filter((path) => existsSync(path));
173
+ }
174
+
152
175
  function syncAdapter(pi: ExtensionAPI, ctx: ExtensionContext, state: AdapterState): void {
153
176
  state.promptSkills = extractPiPromptSkills(ctx.getSystemPrompt());
154
177
 
@@ -4,6 +4,13 @@ export interface PromptSkill {
4
4
  filePath: string;
5
5
  }
6
6
 
7
+ export interface StructuredPromptSkill {
8
+ name: string;
9
+ description: string;
10
+ filePath: string;
11
+ disableModelInvocation?: boolean;
12
+ }
13
+
7
14
  const CODEX_GUIDELINES = [
8
15
  "Use `exec_command` for shell commands, file inspection, builds, and tests; prefer `rg` / `rg --files` for discovery and focused commands over truncation.",
9
16
  "Use `apply_patch` for text-file changes, including creates/deletes/moves; group related multi-file edits into one patch.",
@@ -56,6 +63,27 @@ export function extractPiPromptSkills(prompt: string): PromptSkill[] {
56
63
  }));
57
64
  }
58
65
 
66
+ export function promptSkillsFromStructuredSkills(skills: readonly StructuredPromptSkill[] | undefined): PromptSkill[] {
67
+ if (!Array.isArray(skills)) {
68
+ return [];
69
+ }
70
+
71
+ return skills
72
+ .filter((skill) => !skill.disableModelInvocation)
73
+ .map((skill) => ({
74
+ name: skill.name,
75
+ description: skill.description,
76
+ filePath: skill.filePath,
77
+ }));
78
+ }
79
+
80
+ export function resolvePromptSkills(
81
+ structuredSkills: readonly StructuredPromptSkill[] | undefined,
82
+ fallbackSkills: readonly PromptSkill[],
83
+ ): PromptSkill[] {
84
+ return structuredSkills === undefined ? [...fallbackSkills] : promptSkillsFromStructuredSkills(structuredSkills);
85
+ }
86
+
59
87
  function injectSkills(prompt: string, skills: PromptSkill[]): string {
60
88
  if (skills.length === 0 || /\n## Skills\b/.test(prompt) || /<skills_instructions>/.test(prompt)) {
61
89
  return prompt;