@elyracode/coding-agent 0.1.0 → 0.3.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.
Files changed (177) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cli/config-selector.d.ts +1 -1
  3. package/dist/cli/config-selector.d.ts.map +1 -1
  4. package/dist/cli/config-selector.js +1 -1
  5. package/dist/cli/config-selector.js.map +1 -1
  6. package/dist/config.d.ts +1 -1
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +2 -2
  9. package/dist/config.js.map +1 -1
  10. package/dist/core/agent-session-runtime.d.ts +1 -0
  11. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  12. package/dist/core/agent-session-runtime.js +35 -0
  13. package/dist/core/agent-session-runtime.js.map +1 -1
  14. package/dist/core/agent-session.d.ts +7 -1
  15. package/dist/core/agent-session.d.ts.map +1 -1
  16. package/dist/core/agent-session.js +55 -3
  17. package/dist/core/agent-session.js.map +1 -1
  18. package/dist/core/bash-executor.d.ts.map +1 -1
  19. package/dist/core/bash-executor.js +1 -1
  20. package/dist/core/bash-executor.js.map +1 -1
  21. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  22. package/dist/core/compaction/branch-summarization.js +1 -1
  23. package/dist/core/compaction/branch-summarization.js.map +1 -1
  24. package/dist/core/compaction/compaction.d.ts.map +1 -1
  25. package/dist/core/compaction/compaction.js +1 -1
  26. package/dist/core/compaction/compaction.js.map +1 -1
  27. package/dist/core/extensions/loader.d.ts.map +1 -1
  28. package/dist/core/extensions/loader.js +3 -3
  29. package/dist/core/extensions/loader.js.map +1 -1
  30. package/dist/core/extensions/runner.d.ts.map +1 -1
  31. package/dist/core/extensions/runner.js +1 -1
  32. package/dist/core/extensions/runner.js.map +1 -1
  33. package/dist/core/extensions/types.d.ts +9 -9
  34. package/dist/core/extensions/types.d.ts.map +1 -1
  35. package/dist/core/extensions/types.js.map +1 -1
  36. package/dist/core/memory.d.ts +23 -0
  37. package/dist/core/memory.d.ts.map +1 -0
  38. package/dist/core/memory.js +173 -0
  39. package/dist/core/memory.js.map +1 -0
  40. package/dist/core/package-manager.d.ts.map +1 -1
  41. package/dist/core/package-manager.js +12 -12
  42. package/dist/core/package-manager.js.map +1 -1
  43. package/dist/core/session-manager.d.ts +6 -6
  44. package/dist/core/session-manager.d.ts.map +1 -1
  45. package/dist/core/session-manager.js +4 -4
  46. package/dist/core/session-manager.js.map +1 -1
  47. package/dist/core/settings-manager.d.ts +6 -0
  48. package/dist/core/settings-manager.d.ts.map +1 -1
  49. package/dist/core/settings-manager.js +16 -0
  50. package/dist/core/settings-manager.js.map +1 -1
  51. package/dist/core/smart-router.d.ts +43 -0
  52. package/dist/core/smart-router.d.ts.map +1 -0
  53. package/dist/core/smart-router.js +206 -0
  54. package/dist/core/smart-router.js.map +1 -0
  55. package/dist/core/stack-detector.d.ts +21 -0
  56. package/dist/core/stack-detector.d.ts.map +1 -0
  57. package/dist/core/stack-detector.js +120 -0
  58. package/dist/core/stack-detector.js.map +1 -0
  59. package/dist/core/system-prompt.d.ts +4 -0
  60. package/dist/core/system-prompt.d.ts.map +1 -1
  61. package/dist/core/system-prompt.js +27 -1
  62. package/dist/core/system-prompt.js.map +1 -1
  63. package/dist/core/tools/bash.d.ts +2 -2
  64. package/dist/core/tools/bash.d.ts.map +1 -1
  65. package/dist/core/tools/bash.js +3 -3
  66. package/dist/core/tools/bash.js.map +1 -1
  67. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  68. package/dist/core/tools/output-accumulator.js +1 -1
  69. package/dist/core/tools/output-accumulator.js.map +1 -1
  70. package/dist/migrations.d.ts.map +1 -1
  71. package/dist/migrations.js +1 -1
  72. package/dist/migrations.js.map +1 -1
  73. package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
  74. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  75. package/dist/modes/interactive/components/settings-selector.js +20 -0
  76. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  77. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  78. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  79. package/dist/modes/interactive/interactive-mode.js +26 -0
  80. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  81. package/dist/package-manager-cli.d.ts.map +1 -1
  82. package/dist/package-manager-cli.js +10 -10
  83. package/dist/package-manager-cli.js.map +1 -1
  84. package/dist/utils/clipboard-image.d.ts.map +1 -1
  85. package/dist/utils/clipboard-image.js +1 -1
  86. package/dist/utils/clipboard-image.js.map +1 -1
  87. package/docs/extensions.md +17 -17
  88. package/docs/index.md +1 -1
  89. package/docs/prompt-templates.md +1 -1
  90. package/docs/providers.md +1 -1
  91. package/docs/quickstart.md +5 -5
  92. package/docs/rpc.md +6 -6
  93. package/docs/sdk.md +2 -2
  94. package/docs/session-format.md +3 -3
  95. package/docs/settings.md +4 -4
  96. package/docs/skills.md +2 -2
  97. package/docs/termux.md +3 -3
  98. package/docs/themes.md +1 -1
  99. package/docs/tui.md +1 -1
  100. package/docs/usage.md +2 -2
  101. package/examples/extensions/auto-commit-on-exit.ts +5 -5
  102. package/examples/extensions/bash-spawn-hook.ts +2 -2
  103. package/examples/extensions/bookmark.ts +5 -5
  104. package/examples/extensions/border-status-editor.ts +7 -7
  105. package/examples/extensions/built-in-tool-renderer.ts +5 -5
  106. package/examples/extensions/claude-rules.ts +3 -3
  107. package/examples/extensions/commands.ts +4 -4
  108. package/examples/extensions/confirm-destructive.ts +3 -3
  109. package/examples/extensions/custom-compaction.ts +2 -2
  110. package/examples/extensions/custom-footer.ts +2 -2
  111. package/examples/extensions/custom-header.ts +3 -3
  112. package/examples/extensions/custom-provider-anthropic/index.ts +2 -2
  113. package/examples/extensions/custom-provider-anthropic/package.json +2 -2
  114. package/examples/extensions/custom-provider-gitlab-duo/index.ts +2 -2
  115. package/examples/extensions/custom-provider-gitlab-duo/package.json +2 -2
  116. package/examples/extensions/dirty-repo-guard.ts +7 -7
  117. package/examples/extensions/doom-overlay/index.ts +2 -2
  118. package/examples/extensions/dynamic-resources/index.ts +2 -2
  119. package/examples/extensions/dynamic-tools.ts +4 -4
  120. package/examples/extensions/event-bus.ts +8 -8
  121. package/examples/extensions/file-trigger.ts +3 -3
  122. package/examples/extensions/git-checkpoint.ts +7 -7
  123. package/examples/extensions/github-issue-autocomplete.ts +6 -6
  124. package/examples/extensions/handoff.ts +2 -2
  125. package/examples/extensions/hello.ts +2 -2
  126. package/examples/extensions/hidden-thinking-label.ts +3 -3
  127. package/examples/extensions/inline-bash.ts +3 -3
  128. package/examples/extensions/input-transform.ts +2 -2
  129. package/examples/extensions/interactive-shell.ts +2 -2
  130. package/examples/extensions/mac-system-theme.ts +3 -3
  131. package/examples/extensions/message-renderer.ts +4 -4
  132. package/examples/extensions/minimal-mode.ts +8 -8
  133. package/examples/extensions/modal-editor.ts +2 -2
  134. package/examples/extensions/model-status.ts +2 -2
  135. package/examples/extensions/notify.ts +2 -2
  136. package/examples/extensions/overlay-qa-tests.ts +14 -14
  137. package/examples/extensions/overlay-test.ts +2 -2
  138. package/examples/extensions/permission-gate.ts +2 -2
  139. package/examples/extensions/pirate.ts +3 -3
  140. package/examples/extensions/plan-mode/index.ts +22 -22
  141. package/examples/extensions/preset.ts +23 -23
  142. package/examples/extensions/prompt-customizer.ts +2 -2
  143. package/examples/extensions/protected-paths.ts +2 -2
  144. package/examples/extensions/provider-payload.ts +3 -3
  145. package/examples/extensions/qna.ts +2 -2
  146. package/examples/extensions/question.ts +2 -2
  147. package/examples/extensions/questionnaire.ts +2 -2
  148. package/examples/extensions/rainbow-editor.ts +2 -2
  149. package/examples/extensions/reload-runtime.ts +4 -4
  150. package/examples/extensions/rpc-demo.ts +10 -10
  151. package/examples/extensions/sandbox/index.ts +8 -8
  152. package/examples/extensions/sandbox/package.json +2 -2
  153. package/examples/extensions/send-user-message.ts +13 -13
  154. package/examples/extensions/session-name.ts +4 -4
  155. package/examples/extensions/shutdown-command.ts +10 -10
  156. package/examples/extensions/snake.ts +3 -3
  157. package/examples/extensions/space-invaders.ts +3 -3
  158. package/examples/extensions/ssh.ts +10 -10
  159. package/examples/extensions/status-line.ts +4 -4
  160. package/examples/extensions/structured-output.ts +2 -2
  161. package/examples/extensions/subagent/index.ts +3 -3
  162. package/examples/extensions/summarize.ts +2 -2
  163. package/examples/extensions/system-prompt-header.ts +3 -3
  164. package/examples/extensions/tic-tac-toe.ts +15 -15
  165. package/examples/extensions/timed-confirm.ts +4 -4
  166. package/examples/extensions/titlebar-spinner.ts +8 -8
  167. package/examples/extensions/todo.ts +5 -5
  168. package/examples/extensions/tool-override.ts +3 -3
  169. package/examples/extensions/tools.ts +9 -9
  170. package/examples/extensions/trigger-compact.ts +3 -3
  171. package/examples/extensions/truncated-tool.ts +3 -3
  172. package/examples/extensions/widget-placement.ts +2 -2
  173. package/examples/extensions/with-deps/index.ts +2 -2
  174. package/examples/extensions/with-deps/package.json +2 -2
  175. package/examples/extensions/working-indicator.ts +5 -5
  176. package/examples/extensions/working-message-test.ts +2 -2
  177. package/package.json +5 -5
@@ -35,12 +35,12 @@ function getTextContent(message: AssistantMessage): string {
35
35
  .join("\n");
36
36
  }
37
37
 
38
- export default function planModeExtension(pi: ExtensionAPI): void {
38
+ export default function planModeExtension(elyra: ExtensionAPI): void {
39
39
  let planModeEnabled = false;
40
40
  let executionMode = false;
41
41
  let todoItems: TodoItem[] = [];
42
42
 
43
- pi.registerFlag("plan", {
43
+ elyra.registerFlag("plan", {
44
44
  description: "Start in plan mode (read-only exploration)",
45
45
  type: "boolean",
46
46
  default: false,
@@ -79,29 +79,29 @@ export default function planModeExtension(pi: ExtensionAPI): void {
79
79
  todoItems = [];
80
80
 
81
81
  if (planModeEnabled) {
82
- pi.setActiveTools(PLAN_MODE_TOOLS);
82
+ elyra.setActiveTools(PLAN_MODE_TOOLS);
83
83
  ctx.ui.notify(`Plan mode enabled. Tools: ${PLAN_MODE_TOOLS.join(", ")}`);
84
84
  } else {
85
- pi.setActiveTools(NORMAL_MODE_TOOLS);
85
+ elyra.setActiveTools(NORMAL_MODE_TOOLS);
86
86
  ctx.ui.notify("Plan mode disabled. Full access restored.");
87
87
  }
88
88
  updateStatus(ctx);
89
89
  }
90
90
 
91
91
  function persistState(): void {
92
- pi.appendEntry("plan-mode", {
92
+ elyra.appendEntry("plan-mode", {
93
93
  enabled: planModeEnabled,
94
94
  todos: todoItems,
95
95
  executing: executionMode,
96
96
  });
97
97
  }
98
98
 
99
- pi.registerCommand("plan", {
99
+ elyra.registerCommand("plan", {
100
100
  description: "Toggle plan mode (read-only exploration)",
101
101
  handler: async (_args, ctx) => togglePlanMode(ctx),
102
102
  });
103
103
 
104
- pi.registerCommand("todos", {
104
+ elyra.registerCommand("todos", {
105
105
  description: "Show current plan todo list",
106
106
  handler: async (_args, ctx) => {
107
107
  if (todoItems.length === 0) {
@@ -113,13 +113,13 @@ export default function planModeExtension(pi: ExtensionAPI): void {
113
113
  },
114
114
  });
115
115
 
116
- pi.registerShortcut(Key.ctrlAlt("p"), {
116
+ elyra.registerShortcut(Key.ctrlAlt("p"), {
117
117
  description: "Toggle plan mode",
118
118
  handler: async (ctx) => togglePlanMode(ctx),
119
119
  });
120
120
 
121
121
  // Block destructive bash commands in plan mode
122
- pi.on("tool_call", async (event) => {
122
+ elyra.on("tool_call", async (event) => {
123
123
  if (!planModeEnabled || event.toolName !== "bash") return;
124
124
 
125
125
  const command = event.input.command as string;
@@ -132,7 +132,7 @@ export default function planModeExtension(pi: ExtensionAPI): void {
132
132
  });
133
133
 
134
134
  // Filter out stale plan mode context when not in plan mode
135
- pi.on("context", async (event) => {
135
+ elyra.on("context", async (event) => {
136
136
  if (planModeEnabled) return;
137
137
 
138
138
  return {
@@ -156,7 +156,7 @@ export default function planModeExtension(pi: ExtensionAPI): void {
156
156
  });
157
157
 
158
158
  // Inject plan/execution context before agent starts
159
- pi.on("before_agent_start", async () => {
159
+ elyra.on("before_agent_start", async () => {
160
160
  if (planModeEnabled) {
161
161
  return {
162
162
  message: {
@@ -205,7 +205,7 @@ After completing a step, include a [DONE:n] tag in your response.`,
205
205
  });
206
206
 
207
207
  // Track progress after each turn
208
- pi.on("turn_end", async (event, ctx) => {
208
+ elyra.on("turn_end", async (event, ctx) => {
209
209
  if (!executionMode || todoItems.length === 0) return;
210
210
  if (!isAssistantMessage(event.message)) return;
211
211
 
@@ -217,18 +217,18 @@ After completing a step, include a [DONE:n] tag in your response.`,
217
217
  });
218
218
 
219
219
  // Handle plan completion and plan mode UI
220
- pi.on("agent_end", async (event, ctx) => {
220
+ elyra.on("agent_end", async (event, ctx) => {
221
221
  // Check if execution is complete
222
222
  if (executionMode && todoItems.length > 0) {
223
223
  if (todoItems.every((t) => t.completed)) {
224
224
  const completedList = todoItems.map((t) => `~~${t.text}~~`).join("\n");
225
- pi.sendMessage(
225
+ elyra.sendMessage(
226
226
  { customType: "plan-complete", content: `**Plan Complete!** ✓\n\n${completedList}`, display: true },
227
227
  { triggerTurn: false },
228
228
  );
229
229
  executionMode = false;
230
230
  todoItems = [];
231
- pi.setActiveTools(NORMAL_MODE_TOOLS);
231
+ elyra.setActiveTools(NORMAL_MODE_TOOLS);
232
232
  updateStatus(ctx);
233
233
  persistState(); // Save cleared state so resume doesn't restore old execution mode
234
234
  }
@@ -249,7 +249,7 @@ After completing a step, include a [DONE:n] tag in your response.`,
249
249
  // Show plan steps and prompt for next action
250
250
  if (todoItems.length > 0) {
251
251
  const todoListText = todoItems.map((t, i) => `${i + 1}. ☐ ${t.text}`).join("\n");
252
- pi.sendMessage(
252
+ elyra.sendMessage(
253
253
  {
254
254
  customType: "plan-todo-list",
255
255
  content: `**Plan Steps (${todoItems.length}):**\n\n${todoListText}`,
@@ -268,28 +268,28 @@ After completing a step, include a [DONE:n] tag in your response.`,
268
268
  if (choice?.startsWith("Execute")) {
269
269
  planModeEnabled = false;
270
270
  executionMode = todoItems.length > 0;
271
- pi.setActiveTools(NORMAL_MODE_TOOLS);
271
+ elyra.setActiveTools(NORMAL_MODE_TOOLS);
272
272
  updateStatus(ctx);
273
273
 
274
274
  const execMessage =
275
275
  todoItems.length > 0
276
276
  ? `Execute the plan. Start with: ${todoItems[0].text}`
277
277
  : "Execute the plan you just created.";
278
- pi.sendMessage(
278
+ elyra.sendMessage(
279
279
  { customType: "plan-mode-execute", content: execMessage, display: true },
280
280
  { triggerTurn: true },
281
281
  );
282
282
  } else if (choice === "Refine the plan") {
283
283
  const refinement = await ctx.ui.editor("Refine the plan:", "");
284
284
  if (refinement?.trim()) {
285
- pi.sendUserMessage(refinement.trim());
285
+ elyra.sendUserMessage(refinement.trim());
286
286
  }
287
287
  }
288
288
  });
289
289
 
290
290
  // Restore state on session start/resume
291
- pi.on("session_start", async (_event, ctx) => {
292
- if (pi.getFlag("plan") === true) {
291
+ elyra.on("session_start", async (_event, ctx) => {
292
+ if (elyra.getFlag("plan") === true) {
293
293
  planModeEnabled = true;
294
294
  }
295
295
 
@@ -333,7 +333,7 @@ After completing a step, include a [DONE:n] tag in your response.`,
333
333
  }
334
334
 
335
335
  if (planModeEnabled) {
336
- pi.setActiveTools(PLAN_MODE_TOOLS);
336
+ elyra.setActiveTools(PLAN_MODE_TOOLS);
337
337
  }
338
338
  updateStatus(ctx);
339
339
  });
@@ -104,14 +104,14 @@ interface OriginalState {
104
104
  tools: string[];
105
105
  }
106
106
 
107
- export default function presetExtension(pi: ExtensionAPI) {
107
+ export default function presetExtension(elyra: ExtensionAPI) {
108
108
  let presets: PresetsConfig = {};
109
109
  let activePresetName: string | undefined;
110
110
  let activePreset: Preset | undefined;
111
111
  let originalState: OriginalState | undefined;
112
112
 
113
113
  // Register --preset CLI flag
114
- pi.registerFlag("preset", {
114
+ elyra.registerFlag("preset", {
115
115
  description: "Preset configuration to use",
116
116
  type: "string",
117
117
  });
@@ -124,8 +124,8 @@ export default function presetExtension(pi: ExtensionAPI) {
124
124
  if (activePresetName === undefined) {
125
125
  originalState = {
126
126
  model: ctx.model,
127
- thinkingLevel: pi.getThinkingLevel(),
128
- tools: pi.getActiveTools(),
127
+ thinkingLevel: elyra.getThinkingLevel(),
128
+ tools: elyra.getActiveTools(),
129
129
  };
130
130
  }
131
131
 
@@ -133,7 +133,7 @@ export default function presetExtension(pi: ExtensionAPI) {
133
133
  if (preset.provider && preset.model) {
134
134
  const model = ctx.modelRegistry.find(preset.provider, preset.model);
135
135
  if (model) {
136
- const success = await pi.setModel(model);
136
+ const success = await elyra.setModel(model);
137
137
  if (!success) {
138
138
  ctx.ui.notify(`Preset "${name}": No API key for ${preset.provider}/${preset.model}`, "warning");
139
139
  }
@@ -144,12 +144,12 @@ export default function presetExtension(pi: ExtensionAPI) {
144
144
 
145
145
  // Apply thinking level if specified
146
146
  if (preset.thinkingLevel) {
147
- pi.setThinkingLevel(preset.thinkingLevel);
147
+ elyra.setThinkingLevel(preset.thinkingLevel);
148
148
  }
149
149
 
150
150
  // Apply tools if specified
151
151
  if (preset.tools && preset.tools.length > 0) {
152
- const allToolNames = pi.getAllTools().map((t) => t.name);
152
+ const allToolNames = elyra.getAllTools().map((t) => t.name);
153
153
  const validTools = preset.tools.filter((t) => allToolNames.includes(t));
154
154
  const invalidTools = preset.tools.filter((t) => !allToolNames.includes(t));
155
155
 
@@ -158,7 +158,7 @@ export default function presetExtension(pi: ExtensionAPI) {
158
158
  }
159
159
 
160
160
  if (validTools.length > 0) {
161
- pi.setActiveTools(validTools);
161
+ elyra.setActiveTools(validTools);
162
162
  }
163
163
  }
164
164
 
@@ -273,12 +273,12 @@ export default function presetExtension(pi: ExtensionAPI) {
273
273
  activePreset = undefined;
274
274
  if (originalState) {
275
275
  if (originalState.model) {
276
- await pi.setModel(originalState.model);
276
+ await elyra.setModel(originalState.model);
277
277
  }
278
- pi.setThinkingLevel(originalState.thinkingLevel);
279
- pi.setActiveTools(originalState.tools);
278
+ elyra.setThinkingLevel(originalState.thinkingLevel);
279
+ elyra.setActiveTools(originalState.tools);
280
280
  } else {
281
- pi.setActiveTools(["read", "bash", "edit", "write"]);
281
+ elyra.setActiveTools(["read", "bash", "edit", "write"]);
282
282
  }
283
283
  ctx.ui.notify("Preset cleared, defaults restored", "info");
284
284
  updateStatus(ctx);
@@ -329,12 +329,12 @@ export default function presetExtension(pi: ExtensionAPI) {
329
329
  activePreset = undefined;
330
330
  if (originalState) {
331
331
  if (originalState.model) {
332
- await pi.setModel(originalState.model);
332
+ await elyra.setModel(originalState.model);
333
333
  }
334
- pi.setThinkingLevel(originalState.thinkingLevel);
335
- pi.setActiveTools(originalState.tools);
334
+ elyra.setThinkingLevel(originalState.thinkingLevel);
335
+ elyra.setActiveTools(originalState.tools);
336
336
  } else {
337
- pi.setActiveTools(["read", "bash", "edit", "write"]);
337
+ elyra.setActiveTools(["read", "bash", "edit", "write"]);
338
338
  }
339
339
  ctx.ui.notify("Preset cleared, defaults restored", "info");
340
340
  updateStatus(ctx);
@@ -349,7 +349,7 @@ export default function presetExtension(pi: ExtensionAPI) {
349
349
  updateStatus(ctx);
350
350
  }
351
351
 
352
- pi.registerShortcut(Key.ctrlShift("u"), {
352
+ elyra.registerShortcut(Key.ctrlShift("u"), {
353
353
  description: "Cycle presets",
354
354
  handler: async (ctx) => {
355
355
  await cyclePreset(ctx);
@@ -357,7 +357,7 @@ export default function presetExtension(pi: ExtensionAPI) {
357
357
  });
358
358
 
359
359
  // Register /preset command
360
- pi.registerCommand("preset", {
360
+ elyra.registerCommand("preset", {
361
361
  description: "Switch preset configuration",
362
362
  handler: async (args, ctx) => {
363
363
  // If preset name provided, apply directly
@@ -383,7 +383,7 @@ export default function presetExtension(pi: ExtensionAPI) {
383
383
  });
384
384
 
385
385
  // Inject preset instructions into system prompt
386
- pi.on("before_agent_start", async (event) => {
386
+ elyra.on("before_agent_start", async (event) => {
387
387
  if (activePreset?.instructions) {
388
388
  return {
389
389
  systemPrompt: `${event.systemPrompt}\n\n${activePreset.instructions}`,
@@ -392,12 +392,12 @@ export default function presetExtension(pi: ExtensionAPI) {
392
392
  });
393
393
 
394
394
  // Initialize on session start
395
- pi.on("session_start", async (_event, ctx) => {
395
+ elyra.on("session_start", async (_event, ctx) => {
396
396
  // Load presets from config files
397
397
  presets = loadPresets(ctx.cwd);
398
398
 
399
399
  // Check for --preset flag
400
- const presetFlag = pi.getFlag("preset");
400
+ const presetFlag = elyra.getFlag("preset");
401
401
  if (typeof presetFlag === "string" && presetFlag) {
402
402
  const preset = presets[presetFlag];
403
403
  if (preset) {
@@ -428,9 +428,9 @@ export default function presetExtension(pi: ExtensionAPI) {
428
428
  });
429
429
 
430
430
  // Persist preset state
431
- pi.on("turn_start", async () => {
431
+ elyra.on("turn_start", async () => {
432
432
  if (activePresetName) {
433
- pi.appendEntry("preset-state", { name: activePresetName });
433
+ elyra.appendEntry("preset-state", { name: activePresetName });
434
434
  }
435
435
  });
436
436
  }
@@ -83,8 +83,8 @@ If you have additional requirements, configure them via --append-system-prompt o
83
83
  return extensionSpecific;
84
84
  }
85
85
 
86
- export default function promptCustomizer(pi: ExtensionAPI) {
87
- pi.on("before_agent_start", async (event) => {
86
+ export default function promptCustomizer(elyra: ExtensionAPI) {
87
+ elyra.on("before_agent_start", async (event) => {
88
88
  const { systemPrompt, systemPromptOptions } = event;
89
89
 
90
90
  const customPrompt = addToolGuidance(systemPromptOptions, systemPrompt);
@@ -7,10 +7,10 @@
7
7
 
8
8
  import type { ExtensionAPI } from "@elyracode/coding-agent";
9
9
 
10
- export default function (pi: ExtensionAPI) {
10
+ export default function (elyra: ExtensionAPI) {
11
11
  const protectedPaths = [".env", ".git/", "node_modules/"];
12
12
 
13
- pi.on("tool_call", async (event, ctx) => {
13
+ elyra.on("tool_call", async (event, ctx) => {
14
14
  if (event.toolName !== "write" && event.toolName !== "edit") {
15
15
  return undefined;
16
16
  }
@@ -2,17 +2,17 @@ import { appendFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import type { ExtensionAPI } from "@elyracode/coding-agent";
4
4
 
5
- export default function (pi: ExtensionAPI) {
5
+ export default function (elyra: ExtensionAPI) {
6
6
  const logFile = join(process.cwd(), ".elyra", "provider-payload.log");
7
7
 
8
- pi.on("before_provider_request", (event) => {
8
+ elyra.on("before_provider_request", (event) => {
9
9
  appendFileSync(logFile, `${JSON.stringify(event.payload, null, 2)}\n\n`, "utf8");
10
10
 
11
11
  // Optional: replace the payload instead of only logging it.
12
12
  // return { ...event.payload, temperature: 0 };
13
13
  });
14
14
 
15
- pi.on("after_provider_response", (event) => {
15
+ elyra.on("after_provider_response", (event) => {
16
16
  appendFileSync(logFile, `[${event.status}] ${JSON.stringify(event.headers)}\n\n`, "utf8");
17
17
  });
18
18
  }
@@ -27,8 +27,8 @@ A:
27
27
 
28
28
  Keep questions in the order they appeared. Be concise.`;
29
29
 
30
- export default function (pi: ExtensionAPI) {
31
- pi.registerCommand("qna", {
30
+ export default function (elyra: ExtensionAPI) {
31
+ elyra.registerCommand("qna", {
32
32
  description: "Extract questions from last assistant message into editor",
33
33
  handler: async (_args, ctx) => {
34
34
  if (!ctx.hasUI) {
@@ -33,8 +33,8 @@ const QuestionParams = Type.Object({
33
33
  options: Type.Array(OptionSchema, { description: "Options for the user to choose from" }),
34
34
  });
35
35
 
36
- export default function question(pi: ExtensionAPI) {
37
- pi.registerTool({
36
+ export default function question(elyra: ExtensionAPI) {
37
+ elyra.registerTool({
38
38
  name: "question",
39
39
  label: "Question",
40
40
  description: "Ask the user a question and let them pick from options. Use when you need user input to proceed.",
@@ -73,8 +73,8 @@ function errorResult(
73
73
  };
74
74
  }
75
75
 
76
- export default function questionnaire(pi: ExtensionAPI) {
77
- pi.registerTool({
76
+ export default function questionnaire(elyra: ExtensionAPI) {
77
+ elyra.registerTool({
78
78
  name: "questionnaire",
79
79
  label: "Questionnaire",
80
80
  description:
@@ -81,8 +81,8 @@ class RainbowEditor extends CustomEditor {
81
81
  }
82
82
  }
83
83
 
84
- export default function (pi: ExtensionAPI) {
85
- pi.on("session_start", (_event, ctx) => {
84
+ export default function (elyra: ExtensionAPI) {
85
+ elyra.on("session_start", (_event, ctx) => {
86
86
  ctx.ui.setEditorComponent((tui, theme, kb) => new RainbowEditor(tui, theme, kb));
87
87
  });
88
88
  }
@@ -8,10 +8,10 @@
8
8
  import type { ExtensionAPI } from "@elyracode/coding-agent";
9
9
  import { Type } from "typebox";
10
10
 
11
- export default function (pi: ExtensionAPI) {
11
+ export default function (elyra: ExtensionAPI) {
12
12
  // Command entrypoint for reload.
13
13
  // Treat reload as terminal for this handler.
14
- pi.registerCommand("reload-runtime", {
14
+ elyra.registerCommand("reload-runtime", {
15
15
  description: "Reload extensions, skills, prompts, and themes",
16
16
  handler: async (_args, ctx) => {
17
17
  await ctx.reload();
@@ -21,13 +21,13 @@ export default function (pi: ExtensionAPI) {
21
21
 
22
22
  // LLM-callable tool. Tools get ExtensionContext, so they cannot call ctx.reload() directly.
23
23
  // Instead, queue a follow-up user command that executes the command above.
24
- pi.registerTool({
24
+ elyra.registerTool({
25
25
  name: "reload_runtime",
26
26
  label: "Reload Runtime",
27
27
  description: "Reload extensions, skills, prompts, and themes",
28
28
  parameters: Type.Object({}),
29
29
  async execute() {
30
- pi.sendUserMessage("/reload-runtime", { deliverAs: "followUp" });
30
+ elyra.sendUserMessage("/reload-runtime", { deliverAs: "followUp" });
31
31
  return {
32
32
  content: [{ type: "text", text: "Queued /reload-runtime as a follow-up command." }],
33
33
  details: {},
@@ -19,31 +19,31 @@
19
19
 
20
20
  import type { ExtensionAPI } from "@elyracode/coding-agent";
21
21
 
22
- export default function (pi: ExtensionAPI) {
22
+ export default function (elyra: ExtensionAPI) {
23
23
  let turnCount = 0;
24
24
 
25
25
  // -- setTitle, setWidget, setStatus on session lifecycle --
26
26
 
27
- pi.on("session_start", async (event, ctx) => {
28
- ctx.ui.setTitle(event.reason === "new" ? "pi RPC Demo (new session)" : "pi RPC Demo");
27
+ elyra.on("session_start", async (event, ctx) => {
28
+ ctx.ui.setTitle(event.reason === "new" ? "elyra RPC Demo (new session)" : "elyra RPC Demo");
29
29
  ctx.ui.setWidget("rpc-demo", ["--- RPC Extension UI Demo ---", "Loaded and ready."]);
30
30
  ctx.ui.setStatus("rpc-demo", `Turns: ${turnCount}`);
31
31
  });
32
32
 
33
33
  // -- setStatus on turn lifecycle --
34
34
 
35
- pi.on("turn_start", async (_event, ctx) => {
35
+ elyra.on("turn_start", async (_event, ctx) => {
36
36
  turnCount++;
37
37
  ctx.ui.setStatus("rpc-demo", `Turn ${turnCount} running...`);
38
38
  });
39
39
 
40
- pi.on("turn_end", async (_event, ctx) => {
40
+ elyra.on("turn_end", async (_event, ctx) => {
41
41
  ctx.ui.setStatus("rpc-demo", `Turn ${turnCount} done`);
42
42
  });
43
43
 
44
44
  // -- select on dangerous tool calls --
45
45
 
46
- pi.on("tool_call", async (event, ctx) => {
46
+ elyra.on("tool_call", async (event, ctx) => {
47
47
  if (event.toolName !== "bash") return undefined;
48
48
 
49
49
  const command = event.input.command as string;
@@ -67,7 +67,7 @@ export default function (pi: ExtensionAPI) {
67
67
 
68
68
  // -- confirm on session clear --
69
69
 
70
- pi.on("session_before_switch", async (event, ctx) => {
70
+ elyra.on("session_before_switch", async (event, ctx) => {
71
71
  if (event.reason !== "new") return;
72
72
  if (!ctx.hasUI) return;
73
73
 
@@ -80,7 +80,7 @@ export default function (pi: ExtensionAPI) {
80
80
 
81
81
  // -- input via command --
82
82
 
83
- pi.registerCommand("rpc-input", {
83
+ elyra.registerCommand("rpc-input", {
84
84
  description: "Prompt for text input (demonstrates ctx.ui.input in RPC)",
85
85
  handler: async (_args, ctx) => {
86
86
  const value = await ctx.ui.input("Enter a value", "type something...");
@@ -94,7 +94,7 @@ export default function (pi: ExtensionAPI) {
94
94
 
95
95
  // -- editor via command --
96
96
 
97
- pi.registerCommand("rpc-editor", {
97
+ elyra.registerCommand("rpc-editor", {
98
98
  description: "Open multi-line editor (demonstrates ctx.ui.editor in RPC)",
99
99
  handler: async (_args, ctx) => {
100
100
  const text = await ctx.ui.editor("Edit some text", "Line 1\nLine 2\nLine 3");
@@ -108,7 +108,7 @@ export default function (pi: ExtensionAPI) {
108
108
 
109
109
  // -- setEditorText via command --
110
110
 
111
- pi.registerCommand("rpc-prefill", {
111
+ elyra.registerCommand("rpc-prefill", {
112
112
  description: "Prefill the input editor (demonstrates ctx.ui.setEditorText in RPC)",
113
113
  handler: async (_args, ctx) => {
114
114
  ctx.ui.setEditorText("This text was set by the rpc-demo extension.");
@@ -198,8 +198,8 @@ function createSandboxedBashOps(): BashOperations {
198
198
  };
199
199
  }
200
200
 
201
- export default function (pi: ExtensionAPI) {
202
- pi.registerFlag("no-sandbox", {
201
+ export default function (elyra: ExtensionAPI) {
202
+ elyra.registerFlag("no-sandbox", {
203
203
  description: "Disable OS-level sandboxing for bash commands",
204
204
  type: "boolean",
205
205
  default: false,
@@ -211,7 +211,7 @@ export default function (pi: ExtensionAPI) {
211
211
  let sandboxEnabled = false;
212
212
  let sandboxInitialized = false;
213
213
 
214
- pi.registerTool({
214
+ elyra.registerTool({
215
215
  ...localBash,
216
216
  label: "bash (sandboxed)",
217
217
  async execute(id, params, signal, onUpdate, _ctx) {
@@ -226,13 +226,13 @@ export default function (pi: ExtensionAPI) {
226
226
  },
227
227
  });
228
228
 
229
- pi.on("user_bash", () => {
229
+ elyra.on("user_bash", () => {
230
230
  if (!sandboxEnabled || !sandboxInitialized) return;
231
231
  return { operations: createSandboxedBashOps() };
232
232
  });
233
233
 
234
- pi.on("session_start", async (_event, ctx) => {
235
- const noSandbox = pi.getFlag("no-sandbox") as boolean;
234
+ elyra.on("session_start", async (_event, ctx) => {
235
+ const noSandbox = elyra.getFlag("no-sandbox") as boolean;
236
236
 
237
237
  if (noSandbox) {
238
238
  sandboxEnabled = false;
@@ -284,7 +284,7 @@ export default function (pi: ExtensionAPI) {
284
284
  }
285
285
  });
286
286
 
287
- pi.on("session_shutdown", async () => {
287
+ elyra.on("session_shutdown", async () => {
288
288
  if (sandboxInitialized) {
289
289
  try {
290
290
  await SandboxManager.reset();
@@ -294,7 +294,7 @@ export default function (pi: ExtensionAPI) {
294
294
  }
295
295
  });
296
296
 
297
- pi.registerCommand("sandbox", {
297
+ elyra.registerCommand("sandbox", {
298
298
  description: "Show sandbox configuration",
299
299
  handler: async (_args, ctx) => {
300
300
  if (!sandboxEnabled) {
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "elyra-extension-sandbox",
3
3
  "private": true,
4
- "version": "0.1.0",
5
- "type": "module",
4
+ "version": "0.3.0",
5
+ "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
8
8
  "build": "echo 'nothing to build'",
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Send User Message Example
3
3
  *
4
- * Demonstrates pi.sendUserMessage() for sending user messages from extensions.
5
- * Unlike pi.sendMessage() which sends custom messages, sendUserMessage() sends
4
+ * Demonstrates elyra.sendUserMessage() for sending user messages from extensions.
5
+ * Unlike elyra.sendMessage() which sends custom messages, sendUserMessage() sends
6
6
  * actual user messages that appear in the conversation as if typed by the user.
7
7
  *
8
8
  * Usage:
@@ -13,9 +13,9 @@
13
13
 
14
14
  import type { ExtensionAPI } from "@elyracode/coding-agent";
15
15
 
16
- export default function (pi: ExtensionAPI) {
16
+ export default function (elyra: ExtensionAPI) {
17
17
  // Simple command that sends a user message
18
- pi.registerCommand("ask", {
18
+ elyra.registerCommand("ask", {
19
19
  description: "Send a user message to the agent",
20
20
  handler: async (args, ctx) => {
21
21
  if (!args.trim()) {
@@ -30,12 +30,12 @@ export default function (pi: ExtensionAPI) {
30
30
  return;
31
31
  }
32
32
 
33
- pi.sendUserMessage(args);
33
+ elyra.sendUserMessage(args);
34
34
  },
35
35
  });
36
36
 
37
37
  // Command that steers the agent mid-conversation
38
- pi.registerCommand("steer", {
38
+ elyra.registerCommand("steer", {
39
39
  description: "Send a steering message (interrupts current processing)",
40
40
  handler: async (args, ctx) => {
41
41
  if (!args.trim()) {
@@ -45,16 +45,16 @@ export default function (pi: ExtensionAPI) {
45
45
 
46
46
  if (ctx.isIdle()) {
47
47
  // Not streaming, just send normally
48
- pi.sendUserMessage(args);
48
+ elyra.sendUserMessage(args);
49
49
  } else {
50
50
  // Streaming - use steer to interrupt
51
- pi.sendUserMessage(args, { deliverAs: "steer" });
51
+ elyra.sendUserMessage(args, { deliverAs: "steer" });
52
52
  }
53
53
  },
54
54
  });
55
55
 
56
56
  // Command that queues a follow-up message
57
- pi.registerCommand("followup", {
57
+ elyra.registerCommand("followup", {
58
58
  description: "Queue a follow-up message (waits for current processing)",
59
59
  handler: async (args, ctx) => {
60
60
  if (!args.trim()) {
@@ -64,17 +64,17 @@ export default function (pi: ExtensionAPI) {
64
64
 
65
65
  if (ctx.isIdle()) {
66
66
  // Not streaming, just send normally
67
- pi.sendUserMessage(args);
67
+ elyra.sendUserMessage(args);
68
68
  } else {
69
69
  // Streaming - queue as follow-up
70
- pi.sendUserMessage(args, { deliverAs: "followUp" });
70
+ elyra.sendUserMessage(args, { deliverAs: "followUp" });
71
71
  ctx.ui.notify("Follow-up queued", "info");
72
72
  }
73
73
  },
74
74
  });
75
75
 
76
76
  // Example with content array (text + images would go here)
77
- pi.registerCommand("askwith", {
77
+ elyra.registerCommand("askwith", {
78
78
  description: "Send a user message with structured content",
79
79
  handler: async (args, ctx) => {
80
80
  if (!args.trim()) {
@@ -88,7 +88,7 @@ export default function (pi: ExtensionAPI) {
88
88
  }
89
89
 
90
90
  // sendUserMessage accepts string or (TextContent | ImageContent)[]
91
- pi.sendUserMessage([
91
+ elyra.sendUserMessage([
92
92
  { type: "text", text: `User request: ${args}` },
93
93
  { type: "text", text: "Please respond concisely." },
94
94
  ]);