@howaboua/pi-codex-conversion 1.0.0 → 1.0.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.
package/README.md CHANGED
@@ -79,6 +79,7 @@ pi install git:github.com/IgorWarzocha/pi-codex-conversion
79
79
  The adapter does not build a standalone replacement prompt anymore. Instead it:
80
80
 
81
81
  - keeps Pi's tool descriptions, Pi docs section, AGENTS/project context, skills inventory, and date/cwd when Pi already surfaced them
82
+ - adds the current shell to the transformed prompt so quoting and escaping can match the runtime environment
82
83
  - rewrites the top-level role framing to Codex-style wording
83
84
  - adds a small Codex delta to the existing `Guidelines` section
84
85
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@howaboua/pi-codex-conversion",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
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
@@ -15,6 +15,8 @@ interface AdapterState {
15
15
  promptSkills: PromptSkill[];
16
16
  }
17
17
 
18
+ const ADAPTER_TOOL_NAMES = [...CORE_ADAPTER_TOOL_NAMES, VIEW_IMAGE_TOOL_NAME];
19
+
18
20
  function getCommandArg(args: unknown): string | undefined {
19
21
  if (!args || typeof args !== "object" || !("cmd" in args) || typeof args.cmd !== "string") {
20
22
  return undefined;
@@ -63,7 +65,12 @@ export default function codexConversion(pi: ExtensionAPI) {
63
65
  if (!isCodexLikeContext(ctx)) {
64
66
  return undefined;
65
67
  }
66
- return { systemPrompt: buildCodexSystemPrompt(event.systemPrompt, { skills: state.promptSkills }) };
68
+ return {
69
+ systemPrompt: buildCodexSystemPrompt(event.systemPrompt, {
70
+ skills: state.promptSkills,
71
+ shell: process.env.SHELL || "/bin/bash",
72
+ }),
73
+ };
67
74
  });
68
75
  }
69
76
 
@@ -80,7 +87,7 @@ function syncAdapter(pi: ExtensionAPI, ctx: ExtensionContext, state: AdapterStat
80
87
  }
81
88
 
82
89
  function enableAdapter(pi: ExtensionAPI, ctx: ExtensionContext, state: AdapterState): void {
83
- const toolNames = getAdapterToolNames(ctx);
90
+ const toolNames = mergeAdapterTools(pi.getActiveTools(), getAdapterToolNames(ctx));
84
91
  if (!state.enabled) {
85
92
  // Preserve the previous active set once so switching away from Codex-like
86
93
  // models restores the user's existing Pi tool configuration.
@@ -93,7 +100,8 @@ function enableAdapter(pi: ExtensionAPI, ctx: ExtensionContext, state: AdapterSt
93
100
 
94
101
  function disableAdapter(pi: ExtensionAPI, ctx: ExtensionContext, state: AdapterState): void {
95
102
  if (state.enabled) {
96
- pi.setActiveTools(state.previousToolNames && state.previousToolNames.length > 0 ? state.previousToolNames : DEFAULT_TOOL_NAMES);
103
+ const previousToolNames = state.previousToolNames && state.previousToolNames.length > 0 ? state.previousToolNames : DEFAULT_TOOL_NAMES;
104
+ pi.setActiveTools(restoreTools(previousToolNames, pi.getActiveTools()));
97
105
  state.enabled = false;
98
106
  }
99
107
  setStatus(ctx, false);
@@ -110,3 +118,18 @@ function getAdapterToolNames(ctx: ExtensionContext): string[] {
110
118
  }
111
119
  return [...CORE_ADAPTER_TOOL_NAMES];
112
120
  }
121
+
122
+ export function mergeAdapterTools(activeTools: string[], adapterTools: string[]): string[] {
123
+ const preservedTools = activeTools.filter((toolName) => !DEFAULT_TOOL_NAMES.includes(toolName) && !ADAPTER_TOOL_NAMES.includes(toolName));
124
+ return [...adapterTools, ...preservedTools];
125
+ }
126
+
127
+ export function restoreTools(previousTools: string[], activeTools: string[]): string[] {
128
+ const restored = [...previousTools];
129
+ for (const toolName of activeTools) {
130
+ if (!ADAPTER_TOOL_NAMES.includes(toolName) && !restored.includes(toolName)) {
131
+ restored.push(toolName);
132
+ }
133
+ }
134
+ return restored;
135
+ }
@@ -30,6 +30,13 @@ function insertBeforeTrailingContext(prompt: string, section: string): string {
30
30
  return `${prompt}\n\n${section}`;
31
31
  }
32
32
 
33
+ function injectShell(prompt: string, shell?: string): string {
34
+ if (!shell || /\nCurrent shell:/.test(prompt)) {
35
+ return prompt;
36
+ }
37
+ return insertBeforeTrailingContext(prompt, `Current shell: ${shell}`);
38
+ }
39
+
33
40
  function decodeXml(text: string): string {
34
41
  return text
35
42
  .replace(/'/g, "'")
@@ -106,6 +113,6 @@ function injectGuidelines(prompt: string): string {
106
113
  return `${prompt.slice(0, match.index)}${replacement}${prompt.slice(match.index + match[0].length)}`;
107
114
  }
108
115
 
109
- export function buildCodexSystemPrompt(basePrompt: string, options: { skills?: PromptSkill[] } = {}): string {
110
- return injectSkills(injectGuidelines(rewriteIntro(basePrompt)), options.skills ?? []);
116
+ export function buildCodexSystemPrompt(basePrompt: string, options: { skills?: PromptSkill[]; shell?: string } = {}): string {
117
+ return injectShell(injectSkills(injectGuidelines(rewriteIntro(basePrompt)), options.skills ?? []), options.shell);
111
118
  }