one-code-extension 0.1.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 (153) hide show
  1. package/LICENSE +32 -0
  2. package/README.md +202 -0
  3. package/agents/explore.md +24 -0
  4. package/agents/general-purpose.md +21 -0
  5. package/agents/plan.md +22 -0
  6. package/docs/decisions/auto-mode.md +526 -0
  7. package/docs/decisions/branding.md +127 -0
  8. package/docs/decisions/code-review-remediation.md +106 -0
  9. package/docs/decisions/compaction.md +140 -0
  10. package/docs/decisions/distribution.md +133 -0
  11. package/docs/decisions/hooks.md +64 -0
  12. package/docs/decisions/lsp.md +58 -0
  13. package/docs/decisions/mcp.md +104 -0
  14. package/docs/decisions/memory-state.md +170 -0
  15. package/docs/decisions/model-policy.md +126 -0
  16. package/docs/decisions/modes.md +178 -0
  17. package/docs/decisions/skills-plugins.md +56 -0
  18. package/docs/decisions/subagents-workflows.md +225 -0
  19. package/docs/decisions/system-prompt.md +98 -0
  20. package/docs/decisions/tools.md +407 -0
  21. package/docs/decisions/tui.md +202 -0
  22. package/docs/decisions.md +148 -0
  23. package/extensions/ask-user/index.ts +124 -0
  24. package/extensions/ask-user/questions.ts +60 -0
  25. package/extensions/auto-mode/actions.ts +78 -0
  26. package/extensions/auto-mode/classifier.ts +388 -0
  27. package/extensions/auto-mode/config.ts +237 -0
  28. package/extensions/auto-mode/decision-log.ts +60 -0
  29. package/extensions/auto-mode/defaults.ts +65 -0
  30. package/extensions/auto-mode/instructions.ts +74 -0
  31. package/extensions/auto-mode/model-picker.ts +225 -0
  32. package/extensions/auto-mode/model-select.ts +178 -0
  33. package/extensions/auto-mode/paths.ts +109 -0
  34. package/extensions/auto-mode/pause.ts +96 -0
  35. package/extensions/auto-mode/prompt.ts +307 -0
  36. package/extensions/auto-mode/rules.ts +96 -0
  37. package/extensions/auto-mode/safety-floor.ts +100 -0
  38. package/extensions/auto-mode/sensitive.ts +137 -0
  39. package/extensions/auto-mode/shell-analysis.ts +702 -0
  40. package/extensions/background/index.ts +405 -0
  41. package/extensions/background/registry.ts +81 -0
  42. package/extensions/background/wakeup.ts +41 -0
  43. package/extensions/bash/background.ts +136 -0
  44. package/extensions/bash/index.ts +149 -0
  45. package/extensions/branding/assistant-marker.ts +53 -0
  46. package/extensions/branding/index.ts +366 -0
  47. package/extensions/branding/prompt-editor.ts +42 -0
  48. package/extensions/branding/prompt-marker.ts +29 -0
  49. package/extensions/branding/startup.ts +152 -0
  50. package/extensions/claude-compat/index.ts +50 -0
  51. package/extensions/claude-context/index.ts +79 -0
  52. package/extensions/compaction/index.ts +231 -0
  53. package/extensions/compaction/prompt.ts +191 -0
  54. package/extensions/context-management/index.ts +147 -0
  55. package/extensions/effort/index.ts +216 -0
  56. package/extensions/effort/slider.ts +253 -0
  57. package/extensions/exit/index.ts +28 -0
  58. package/extensions/file-tracker/index.ts +103 -0
  59. package/extensions/file-tracker/tracker.ts +145 -0
  60. package/extensions/hooks/debug.ts +53 -0
  61. package/extensions/hooks/executor.ts +132 -0
  62. package/extensions/hooks/index.ts +310 -0
  63. package/extensions/hooks/matcher.ts +72 -0
  64. package/extensions/hooks/plugin-hooks.ts +79 -0
  65. package/extensions/hooks/protocol.ts +151 -0
  66. package/extensions/hooks/settings.ts +163 -0
  67. package/extensions/hooks/trust.ts +151 -0
  68. package/extensions/lib/branch-restore.ts +35 -0
  69. package/extensions/lib/claude-context.ts +148 -0
  70. package/extensions/lib/deferred.ts +119 -0
  71. package/extensions/lib/git.ts +14 -0
  72. package/extensions/lib/memory.ts +219 -0
  73. package/extensions/lib/model-policy.ts +436 -0
  74. package/extensions/lib/model-tier.ts +99 -0
  75. package/extensions/lib/notifications.ts +18 -0
  76. package/extensions/lib/paths.ts +26 -0
  77. package/extensions/lib/per-cwd.ts +21 -0
  78. package/extensions/lib/persisted-output.ts +70 -0
  79. package/extensions/lib/pi-version.ts +54 -0
  80. package/extensions/lib/plugins.ts +227 -0
  81. package/extensions/lib/reminders.ts +212 -0
  82. package/extensions/lib/scratchpad.ts +68 -0
  83. package/extensions/lib/tui-render.ts +522 -0
  84. package/extensions/lsp/client.ts +278 -0
  85. package/extensions/lsp/format.ts +46 -0
  86. package/extensions/lsp/index.ts +193 -0
  87. package/extensions/lsp/protocol.ts +64 -0
  88. package/extensions/lsp/servers.ts +79 -0
  89. package/extensions/mcp/client.ts +205 -0
  90. package/extensions/mcp/config.ts +199 -0
  91. package/extensions/mcp/index.ts +373 -0
  92. package/extensions/mcp/schema.ts +161 -0
  93. package/extensions/memory/index.ts +90 -0
  94. package/extensions/notebook/index.ts +77 -0
  95. package/extensions/notebook/notebook.ts +108 -0
  96. package/extensions/permissions/index.ts +876 -0
  97. package/extensions/permissions/matcher.ts +455 -0
  98. package/extensions/permissions/modes.ts +107 -0
  99. package/extensions/permissions/protected-paths.ts +125 -0
  100. package/extensions/permissions/settings.ts +98 -0
  101. package/extensions/plan-mode/index.ts +209 -0
  102. package/extensions/plan-mode/reminder.ts +33 -0
  103. package/extensions/plan-mode/slug.ts +28 -0
  104. package/extensions/plan-mode/viewer.ts +124 -0
  105. package/extensions/plugins/index.ts +115 -0
  106. package/extensions/plugins/template.ts +42 -0
  107. package/extensions/search-tools/index.ts +0 -0
  108. package/extensions/search-tools/tools.ts +24 -0
  109. package/extensions/skill/index.ts +170 -0
  110. package/extensions/subagents/agents.ts +126 -0
  111. package/extensions/subagents/child.ts +414 -0
  112. package/extensions/subagents/default-model.ts +122 -0
  113. package/extensions/subagents/index.ts +1119 -0
  114. package/extensions/subagents/model-select.ts +346 -0
  115. package/extensions/subagents/rpc-turns.ts +123 -0
  116. package/extensions/subagents/runs.ts +93 -0
  117. package/extensions/subagents/usage.ts +53 -0
  118. package/extensions/subagents/worktree.ts +69 -0
  119. package/extensions/system-prompt/environment.ts +35 -0
  120. package/extensions/system-prompt/index.ts +54 -0
  121. package/extensions/system-prompt/template.ts +103 -0
  122. package/extensions/system-prompt/tiers/common.ts +63 -0
  123. package/extensions/system-prompt/tiers/frontier.ts +24 -0
  124. package/extensions/system-prompt/tiers/low.ts +71 -0
  125. package/extensions/system-prompt/tiers/mid.ts +56 -0
  126. package/extensions/system-reminder/index.ts +37 -0
  127. package/extensions/tasks/index.ts +140 -0
  128. package/extensions/tasks/store.ts +174 -0
  129. package/extensions/todo/index.ts +133 -0
  130. package/extensions/tool-search/index.ts +168 -0
  131. package/extensions/tool-style/index.ts +84 -0
  132. package/extensions/web/index.ts +43 -0
  133. package/extensions/web-fetch/extract.ts +139 -0
  134. package/extensions/web-fetch/index.ts +291 -0
  135. package/extensions/web-fetch/summarize.ts +78 -0
  136. package/extensions/workflow/agent-session.ts +368 -0
  137. package/extensions/workflow/globals.ts +251 -0
  138. package/extensions/workflow/index.ts +364 -0
  139. package/extensions/workflow/journal.ts +75 -0
  140. package/extensions/workflow/permission-gate.ts +71 -0
  141. package/extensions/workflow/run-manager.ts +306 -0
  142. package/extensions/workflow/saved-workflows.ts +45 -0
  143. package/extensions/workflow/script-source.ts +201 -0
  144. package/extensions/workflow/types.ts +99 -0
  145. package/extensions/workflow/vm-runtime.ts +31 -0
  146. package/extensions/workflow/widget.ts +56 -0
  147. package/extensions/worktree/index.ts +266 -0
  148. package/extensions/worktree/rewrite.ts +59 -0
  149. package/package.json +101 -0
  150. package/themes/one-code-light.json +76 -0
  151. package/themes/one-code.json +76 -0
  152. package/types/app.d.ts +5 -0
  153. package/types/community-packages.d.ts +12 -0
@@ -0,0 +1,77 @@
1
+ /**
2
+ * notebook extension — Claude Code's NotebookEdit, deferred behind tool_search
3
+ * (most sessions never touch a notebook, so its schema stays out of the prompt
4
+ * until needed).
5
+ */
6
+
7
+ import { randomUUID } from "node:crypto";
8
+ import { readFileSync, writeFileSync } from "node:fs";
9
+ import { isAbsolute, resolve } from "node:path";
10
+ import { StringEnum } from "@earendil-works/pi-ai";
11
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
12
+ import { Type } from "typebox";
13
+ import { DEFER_CHANNEL } from "../lib/deferred.ts";
14
+ import { ccToolRenderers } from "../lib/tui-render.ts";
15
+ import { applyEdit, type EditMode, parseNotebook } from "./notebook.ts";
16
+
17
+ export default function notebookExtension(pi: ExtensionAPI) {
18
+ pi.registerTool({
19
+ name: "notebook_edit",
20
+ label: "Notebook Edit",
21
+ ...ccToolRenderers("Notebook Edit"),
22
+ description:
23
+ "Edit a Jupyter notebook (.ipynb): replace a cell's source, insert a new cell, or delete a cell. Cells are addressed by their `id`; read the notebook first to get ids. Editing a code cell clears its outputs.",
24
+ parameters: Type.Object({
25
+ path: Type.String({ description: "Absolute or workspace-relative path to the .ipynb file" }),
26
+ edit_mode: StringEnum(["replace", "insert", "delete"] as const),
27
+ cell_id: Type.Optional(
28
+ Type.String({
29
+ description:
30
+ "Target cell id. Required for replace and delete; for insert the new cell goes after it (omit to insert at the top).",
31
+ }),
32
+ ),
33
+ new_source: Type.Optional(Type.String({ description: "New cell source. Required unless deleting." })),
34
+ cell_type: Type.Optional(
35
+ StringEnum(["code", "markdown"] as const, {
36
+ description: "Cell type. Required when inserting; when replacing, changes the cell's type.",
37
+ }),
38
+ ),
39
+ }),
40
+ async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
41
+ const path = isAbsolute(params.path) ? params.path : resolve(ctx.cwd, params.path);
42
+ try {
43
+ const notebook = parseNotebook(readFileSync(path, "utf-8"));
44
+ const { notebook: updated, summary } = applyEdit(
45
+ notebook,
46
+ {
47
+ cellId: params.cell_id,
48
+ newSource: params.new_source,
49
+ cellType: params.cell_type as "code" | "markdown" | undefined,
50
+ editMode: params.edit_mode as EditMode,
51
+ },
52
+ () => randomUUID().slice(0, 8),
53
+ );
54
+ writeFileSync(path, `${JSON.stringify(updated, null, 1)}\n`);
55
+ return {
56
+ content: [{ type: "text", text: `${summary} in ${params.path} (${updated.cells.length} cells).` }],
57
+ details: { path, cellCount: updated.cells.length },
58
+ };
59
+ } catch (error) {
60
+ const code = (error as NodeJS.ErrnoException).code;
61
+ const hint =
62
+ code === "ENOENT"
63
+ ? " — no such file; check the path points to an existing .ipynb"
64
+ : error instanceof SyntaxError
65
+ ? " — the file is not valid notebook JSON"
66
+ : "";
67
+ return {
68
+ content: [{ type: "text", text: `Notebook edit failed: ${(error as Error).message}${hint}` }],
69
+ details: {},
70
+ isError: true,
71
+ };
72
+ }
73
+ },
74
+ });
75
+
76
+ pi.events.emit(DEFER_CHANNEL, { name: "notebook_edit", keywords: ["notebook", "jupyter", "ipynb", "cell"] });
77
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Jupyter notebook editing (pure) — Claude Code's NotebookEdit semantics.
3
+ */
4
+
5
+ export interface NotebookCell {
6
+ cell_type: string;
7
+ id?: string;
8
+ source: string | string[];
9
+ metadata?: Record<string, unknown>;
10
+ outputs?: unknown[];
11
+ execution_count?: number | null;
12
+ }
13
+
14
+ export interface Notebook {
15
+ cells: NotebookCell[];
16
+ [key: string]: unknown;
17
+ }
18
+
19
+ export type EditMode = "replace" | "insert" | "delete";
20
+
21
+ export interface EditRequest {
22
+ cellId?: string;
23
+ newSource?: string;
24
+ cellType?: "code" | "markdown";
25
+ editMode: EditMode;
26
+ }
27
+
28
+ export function parseNotebook(content: string): Notebook {
29
+ const parsed = JSON.parse(content) as Notebook;
30
+ if (!Array.isArray(parsed.cells)) throw new Error("Not a Jupyter notebook: missing 'cells' array");
31
+ return parsed;
32
+ }
33
+
34
+ /** Notebooks store source as a line array with trailing newlines; match that. */
35
+ export function toSourceLines(source: string): string[] {
36
+ const lines = source.split("\n");
37
+ return lines.map((line, i) => (i === lines.length - 1 ? line : `${line}\n`)).filter((l, i) => l !== "" || i === 0);
38
+ }
39
+
40
+ export function findCellIndex(notebook: Notebook, cellId: string): number {
41
+ return notebook.cells.findIndex((cell) => cell.id === cellId);
42
+ }
43
+
44
+ function newCell(cellType: "code" | "markdown", source: string, id: string): NotebookCell {
45
+ const cell: NotebookCell = { cell_type: cellType, id, metadata: {}, source: toSourceLines(source) };
46
+ if (cellType === "code") {
47
+ cell.outputs = [];
48
+ cell.execution_count = null;
49
+ }
50
+ return cell;
51
+ }
52
+
53
+ export interface EditResult {
54
+ notebook: Notebook;
55
+ summary: string;
56
+ }
57
+
58
+ /**
59
+ * Applies one edit and returns a new notebook object. `makeId` supplies the id
60
+ * for inserted cells (injected so callers can keep this deterministic in tests).
61
+ */
62
+ export function applyEdit(notebook: Notebook, request: EditRequest, makeId: () => string): EditResult {
63
+ const cells = [...notebook.cells];
64
+
65
+ if (request.editMode === "delete") {
66
+ if (!request.cellId) throw new Error("cell_id is required for edit_mode 'delete'");
67
+ const index = findCellIndex(notebook, request.cellId);
68
+ if (index === -1) throw new Error(`No cell with id "${request.cellId}"`);
69
+ cells.splice(index, 1);
70
+ return { notebook: { ...notebook, cells }, summary: `Deleted cell ${request.cellId}` };
71
+ }
72
+
73
+ if (request.newSource === undefined) throw new Error("new_source is required unless edit_mode is 'delete'");
74
+
75
+ if (request.editMode === "insert") {
76
+ if (!request.cellType) throw new Error("cell_type is required for edit_mode 'insert'");
77
+ const id = makeId();
78
+ const cell = newCell(request.cellType, request.newSource, id);
79
+ // Claude Code inserts AFTER the given cell; no cell_id means insert first.
80
+ const index = request.cellId ? findCellIndex(notebook, request.cellId) : -1;
81
+ if (request.cellId && index === -1) throw new Error(`No cell with id "${request.cellId}"`);
82
+ cells.splice(index + 1, 0, cell);
83
+ return {
84
+ notebook: { ...notebook, cells },
85
+ summary: `Inserted ${request.cellType} cell ${id}${request.cellId ? ` after ${request.cellId}` : " at the top"}`,
86
+ };
87
+ }
88
+
89
+ if (!request.cellId) throw new Error("cell_id is required for edit_mode 'replace'");
90
+ const index = findCellIndex(notebook, request.cellId);
91
+ if (index === -1) throw new Error(`No cell with id "${request.cellId}"`);
92
+ const existing = cells[index];
93
+ const cellType = (request.cellType ?? existing.cell_type) as "code" | "markdown";
94
+ const replacement: NotebookCell = {
95
+ ...existing,
96
+ cell_type: cellType,
97
+ source: toSourceLines(request.newSource),
98
+ };
99
+ if (cellType === "code") {
100
+ replacement.outputs = [];
101
+ replacement.execution_count = null;
102
+ } else {
103
+ delete replacement.outputs;
104
+ delete replacement.execution_count;
105
+ }
106
+ cells[index] = replacement;
107
+ return { notebook: { ...notebook, cells }, summary: `Replaced cell ${request.cellId}` };
108
+ }