cortex-agents 1.0.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 (40) hide show
  1. package/.opencode/agents/build.md +160 -0
  2. package/.opencode/agents/debug.md +141 -0
  3. package/.opencode/agents/devops.md +109 -0
  4. package/.opencode/agents/fullstack.md +84 -0
  5. package/.opencode/agents/plan.md +188 -0
  6. package/.opencode/agents/security.md +90 -0
  7. package/.opencode/agents/testing.md +89 -0
  8. package/.opencode/skills/code-quality/SKILL.md +251 -0
  9. package/.opencode/skills/deployment-automation/SKILL.md +258 -0
  10. package/.opencode/skills/git-workflow/SKILL.md +281 -0
  11. package/.opencode/skills/security-hardening/SKILL.md +209 -0
  12. package/.opencode/skills/testing-strategies/SKILL.md +159 -0
  13. package/.opencode/skills/web-development/SKILL.md +122 -0
  14. package/LICENSE +17 -0
  15. package/README.md +172 -0
  16. package/dist/cli.d.ts +3 -0
  17. package/dist/cli.d.ts.map +1 -0
  18. package/dist/cli.js +174 -0
  19. package/dist/index.d.ts +4 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +42 -0
  22. package/dist/plugin.d.ts +1 -0
  23. package/dist/plugin.d.ts.map +1 -0
  24. package/dist/plugin.js +3 -0
  25. package/dist/tools/branch.d.ts +35 -0
  26. package/dist/tools/branch.d.ts.map +1 -0
  27. package/dist/tools/branch.js +176 -0
  28. package/dist/tools/cortex.d.ts +11 -0
  29. package/dist/tools/cortex.d.ts.map +1 -0
  30. package/dist/tools/cortex.js +149 -0
  31. package/dist/tools/plan.d.ts +59 -0
  32. package/dist/tools/plan.d.ts.map +1 -0
  33. package/dist/tools/plan.js +177 -0
  34. package/dist/tools/session.d.ts +36 -0
  35. package/dist/tools/session.d.ts.map +1 -0
  36. package/dist/tools/session.js +175 -0
  37. package/dist/tools/worktree.d.ts +45 -0
  38. package/dist/tools/worktree.d.ts.map +1 -0
  39. package/dist/tools/worktree.js +198 -0
  40. package/package.json +55 -0
@@ -0,0 +1,176 @@
1
+ import { tool } from "@opencode-ai/plugin";
2
+ const PROTECTED_BRANCHES = ["main", "master", "develop", "production", "staging"];
3
+ export const create = tool({
4
+ description: "Create and checkout a new git branch with proper naming convention",
5
+ args: {
6
+ name: tool.schema
7
+ .string()
8
+ .describe("Branch name slug (e.g., 'user-authentication', 'fix-login')"),
9
+ type: tool.schema
10
+ .enum(["feature", "bugfix", "hotfix", "refactor", "docs", "test", "chore"])
11
+ .describe("Branch type - determines prefix"),
12
+ },
13
+ async execute(args, context) {
14
+ const { name, type } = args;
15
+ const branchName = `${type}/${name}`;
16
+ // Check if we're in a git repository
17
+ try {
18
+ await Bun.$ `git rev-parse --git-dir`.cwd(context.worktree).text();
19
+ }
20
+ catch {
21
+ return "✗ Error: Not in a git repository";
22
+ }
23
+ // Check if branch already exists
24
+ try {
25
+ const branches = await Bun.$ `git branch --list ${branchName}`.cwd(context.worktree).text();
26
+ if (branches.trim()) {
27
+ return `✗ Error: Branch '${branchName}' already exists.
28
+
29
+ Use branch_switch to switch to it, or choose a different name.`;
30
+ }
31
+ }
32
+ catch {
33
+ // Ignore error, branch check is optional
34
+ }
35
+ // Create and checkout the branch
36
+ try {
37
+ await Bun.$ `git checkout -b ${branchName}`.cwd(context.worktree);
38
+ }
39
+ catch (error) {
40
+ return `✗ Error creating branch: ${error.message || error}`;
41
+ }
42
+ return `✓ Created and switched to branch: ${branchName}
43
+
44
+ You are now on branch '${branchName}'.
45
+ Make your changes and commit when ready.`;
46
+ },
47
+ });
48
+ export const status = tool({
49
+ description: "Get current git branch status - branch name, uncommitted changes, and whether on protected branch",
50
+ args: {},
51
+ async execute(args, context) {
52
+ // Check if we're in a git repository
53
+ try {
54
+ await Bun.$ `git rev-parse --git-dir`.cwd(context.worktree).text();
55
+ }
56
+ catch {
57
+ return "✗ Not in a git repository";
58
+ }
59
+ let currentBranch = "";
60
+ let hasChanges = false;
61
+ let stagedChanges = false;
62
+ let untrackedFiles = false;
63
+ let isProtected = false;
64
+ let aheadBehind = "";
65
+ // Get current branch
66
+ try {
67
+ currentBranch = (await Bun.$ `git branch --show-current`.cwd(context.worktree).text()).trim();
68
+ if (!currentBranch) {
69
+ currentBranch = "(detached HEAD)";
70
+ }
71
+ }
72
+ catch {
73
+ currentBranch = "(unknown)";
74
+ }
75
+ // Check if protected
76
+ isProtected = PROTECTED_BRANCHES.includes(currentBranch);
77
+ // Check for changes
78
+ try {
79
+ const statusOutput = await Bun.$ `git status --porcelain`.cwd(context.worktree).text();
80
+ const lines = statusOutput.trim().split("\n").filter((l) => l);
81
+ for (const line of lines) {
82
+ const status = line.substring(0, 2);
83
+ if (status[0] !== " " && status[0] !== "?") {
84
+ stagedChanges = true;
85
+ }
86
+ if (status[1] !== " " && status[1] !== "?") {
87
+ hasChanges = true;
88
+ }
89
+ if (status === "??") {
90
+ untrackedFiles = true;
91
+ }
92
+ }
93
+ }
94
+ catch {
95
+ // Ignore error
96
+ }
97
+ // Check ahead/behind
98
+ try {
99
+ const result = await Bun.$ `git rev-list --left-right --count HEAD...@{upstream}`.cwd(context.worktree).text();
100
+ const [ahead, behind] = result.trim().split(/\s+/);
101
+ if (parseInt(ahead) > 0 || parseInt(behind) > 0) {
102
+ aheadBehind = `Ahead: ${ahead}, Behind: ${behind}`;
103
+ }
104
+ }
105
+ catch {
106
+ // No upstream or error
107
+ }
108
+ // Build output
109
+ let output = `Git Status:
110
+
111
+ Branch: ${currentBranch}`;
112
+ if (isProtected) {
113
+ output += ` ⚠️ PROTECTED`;
114
+ }
115
+ output += `\n`;
116
+ if (stagedChanges || hasChanges || untrackedFiles) {
117
+ output += `\nChanges:`;
118
+ if (stagedChanges)
119
+ output += `\n • Staged changes (ready to commit)`;
120
+ if (hasChanges)
121
+ output += `\n • Unstaged changes`;
122
+ if (untrackedFiles)
123
+ output += `\n • Untracked files`;
124
+ }
125
+ else {
126
+ output += `\nWorking tree clean.`;
127
+ }
128
+ if (aheadBehind) {
129
+ output += `\n\n${aheadBehind}`;
130
+ }
131
+ if (isProtected) {
132
+ output += `\n
133
+ ⚠️ You are on a protected branch (${currentBranch}).
134
+ Consider creating a feature/bugfix branch before making changes.
135
+ Use branch_create or worktree_create.`;
136
+ }
137
+ return output;
138
+ },
139
+ });
140
+ export const switch_ = tool({
141
+ description: "Switch to an existing git branch",
142
+ args: {
143
+ branch: tool.schema.string().describe("Branch name to switch to"),
144
+ },
145
+ async execute(args, context) {
146
+ const { branch } = args;
147
+ // Check if branch exists
148
+ try {
149
+ const branches = await Bun.$ `git branch --list ${branch}`.cwd(context.worktree).text();
150
+ if (!branches.trim()) {
151
+ // Try remote branch
152
+ const remoteBranches = await Bun.$ `git branch -r --list origin/${branch}`.cwd(context.worktree).text();
153
+ if (!remoteBranches.trim()) {
154
+ return `✗ Error: Branch '${branch}' not found locally or on origin.
155
+
156
+ Use branch_create to create a new branch.`;
157
+ }
158
+ }
159
+ }
160
+ catch {
161
+ // Ignore error, try checkout anyway
162
+ }
163
+ // Switch to branch
164
+ try {
165
+ await Bun.$ `git checkout ${branch}`.cwd(context.worktree);
166
+ }
167
+ catch (error) {
168
+ return `✗ Error switching branch: ${error.message || error}
169
+
170
+ You may have uncommitted changes. Commit or stash them first.`;
171
+ }
172
+ return `✓ Switched to branch: ${branch}`;
173
+ },
174
+ });
175
+ // Export with underscore suffix to avoid reserved word
176
+ export { switch_ as switch };
@@ -0,0 +1,11 @@
1
+ export declare const init: {
2
+ description: string;
3
+ args: {};
4
+ execute(args: Record<string, never>, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
5
+ };
6
+ export declare const status: {
7
+ description: string;
8
+ args: {};
9
+ execute(args: Record<string, never>, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
10
+ };
11
+ //# sourceMappingURL=cortex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cortex.d.ts","sourceRoot":"","sources":["../../src/tools/cortex.ts"],"names":[],"mappings":"AAmEA,eAAO,MAAM,IAAI;;;;CAkDf,CAAC;AAEH,eAAO,MAAM,MAAM;;;;CAyDjB,CAAC"}
@@ -0,0 +1,149 @@
1
+ import { tool } from "@opencode-ai/plugin";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ const CORTEX_DIR = ".cortex";
5
+ const DEFAULT_CONFIG = {
6
+ $schema: "https://k2p5.dev/cortex-config.json",
7
+ version: "1.0.0",
8
+ worktree: {
9
+ root: "../.worktrees",
10
+ autoCleanup: false,
11
+ },
12
+ branches: {
13
+ protected: ["main", "master", "develop"],
14
+ defaultType: "feature",
15
+ },
16
+ plans: {
17
+ namingPattern: "{date}-{type}-{slug}",
18
+ includeMermaid: true,
19
+ },
20
+ sessions: {
21
+ retention: 30,
22
+ includeDecisions: true,
23
+ },
24
+ };
25
+ const GITIGNORE_CONTENT = `# Keep plans (they're valuable documentation)
26
+ !plans/
27
+
28
+ # Ignore session files (local context)
29
+ sessions/
30
+
31
+ # Ignore local config overrides
32
+ config.local.json
33
+ `;
34
+ const README_CONTENT = `# .cortex
35
+
36
+ This directory contains project context for the K2P5 development agents.
37
+
38
+ ## Structure
39
+
40
+ - \`plans/\` - Saved implementation plans (version controlled)
41
+ - \`sessions/\` - Session summaries (gitignored)
42
+ - \`config.json\` - Project configuration
43
+
44
+ ## Plans
45
+
46
+ Plans are saved by the Plan agent and can be loaded by Build/Debug agents.
47
+ They include:
48
+ - Architecture diagrams (mermaid)
49
+ - Task breakdowns
50
+ - Technical decisions
51
+
52
+ ## Sessions
53
+
54
+ Session summaries capture key decisions made during development.
55
+ They are gitignored by default but can be kept if needed.
56
+
57
+ ## Usage
58
+
59
+ The K2P5 agents will automatically use this directory for:
60
+ - Saving implementation plans before coding
61
+ - Recording session summaries with key decisions
62
+ - Managing worktree and branch workflows
63
+ `;
64
+ export const init = tool({
65
+ description: "Initialize .cortex directory in project root for plan storage, session history, and configuration",
66
+ args: {},
67
+ async execute(args, context) {
68
+ const cortexPath = path.join(context.worktree, CORTEX_DIR);
69
+ const plansPath = path.join(cortexPath, "plans");
70
+ const sessionsPath = path.join(cortexPath, "sessions");
71
+ // Check if already exists
72
+ if (fs.existsSync(cortexPath)) {
73
+ const hasConfig = fs.existsSync(path.join(cortexPath, "config.json"));
74
+ const hasPlans = fs.existsSync(plansPath);
75
+ const hasSessions = fs.existsSync(sessionsPath);
76
+ if (hasConfig && hasPlans && hasSessions) {
77
+ return `✓ .cortex directory already initialized at ${cortexPath}`;
78
+ }
79
+ }
80
+ // Create directories
81
+ fs.mkdirSync(plansPath, { recursive: true });
82
+ fs.mkdirSync(sessionsPath, { recursive: true });
83
+ // Create config.json
84
+ fs.writeFileSync(path.join(cortexPath, "config.json"), JSON.stringify(DEFAULT_CONFIG, null, 2));
85
+ // Create .gitignore
86
+ fs.writeFileSync(path.join(cortexPath, ".gitignore"), GITIGNORE_CONTENT);
87
+ // Create README.md
88
+ fs.writeFileSync(path.join(cortexPath, "README.md"), README_CONTENT);
89
+ // Create .gitkeep in plans to ensure it's tracked
90
+ fs.writeFileSync(path.join(plansPath, ".gitkeep"), "");
91
+ return `✓ Initialized .cortex directory at ${cortexPath}
92
+
93
+ Created:
94
+ - .cortex/config.json (configuration)
95
+ - .cortex/plans/ (implementation plans)
96
+ - .cortex/sessions/ (session summaries)
97
+ - .cortex/.gitignore (ignores sessions, keeps plans)
98
+ - .cortex/README.md (documentation)
99
+
100
+ Plans will be version controlled. Sessions are gitignored by default.`;
101
+ },
102
+ });
103
+ export const status = tool({
104
+ description: "Check .cortex directory status - whether it exists, plan count, session count",
105
+ args: {},
106
+ async execute(args, context) {
107
+ const cortexPath = path.join(context.worktree, CORTEX_DIR);
108
+ if (!fs.existsSync(cortexPath)) {
109
+ return `✗ .cortex directory not found at ${cortexPath}
110
+
111
+ Run cortex_init to initialize.`;
112
+ }
113
+ const plansPath = path.join(cortexPath, "plans");
114
+ const sessionsPath = path.join(cortexPath, "sessions");
115
+ let planCount = 0;
116
+ let sessionCount = 0;
117
+ let recentPlans = [];
118
+ let recentSessions = [];
119
+ if (fs.existsSync(plansPath)) {
120
+ const plans = fs
121
+ .readdirSync(plansPath)
122
+ .filter((f) => f.endsWith(".md"))
123
+ .sort()
124
+ .reverse();
125
+ planCount = plans.length;
126
+ recentPlans = plans.slice(0, 3);
127
+ }
128
+ if (fs.existsSync(sessionsPath)) {
129
+ const sessions = fs
130
+ .readdirSync(sessionsPath)
131
+ .filter((f) => f.endsWith(".md"))
132
+ .sort()
133
+ .reverse();
134
+ sessionCount = sessions.length;
135
+ recentSessions = sessions.slice(0, 3);
136
+ }
137
+ let output = `✓ .cortex directory found at ${cortexPath}
138
+
139
+ Plans: ${planCount}`;
140
+ if (recentPlans.length > 0) {
141
+ output += `\n Recent: ${recentPlans.join(", ")}`;
142
+ }
143
+ output += `\n\nSessions: ${sessionCount}`;
144
+ if (recentSessions.length > 0) {
145
+ output += `\n Recent: ${recentSessions.join(", ")}`;
146
+ }
147
+ return output;
148
+ },
149
+ });
@@ -0,0 +1,59 @@
1
+ export declare const save: {
2
+ description: string;
3
+ args: {
4
+ title: import("zod").ZodString;
5
+ type: import("zod").ZodEnum<{
6
+ feature: "feature";
7
+ bugfix: "bugfix";
8
+ refactor: "refactor";
9
+ spike: "spike";
10
+ docs: "docs";
11
+ architecture: "architecture";
12
+ }>;
13
+ content: import("zod").ZodString;
14
+ tasks: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
15
+ };
16
+ execute(args: {
17
+ title: string;
18
+ type: "feature" | "bugfix" | "refactor" | "spike" | "docs" | "architecture";
19
+ content: string;
20
+ tasks?: string[] | undefined;
21
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
22
+ };
23
+ export declare const list: {
24
+ description: string;
25
+ args: {
26
+ type: import("zod").ZodOptional<import("zod").ZodEnum<{
27
+ feature: "feature";
28
+ bugfix: "bugfix";
29
+ refactor: "refactor";
30
+ spike: "spike";
31
+ docs: "docs";
32
+ architecture: "architecture";
33
+ all: "all";
34
+ }>>;
35
+ };
36
+ execute(args: {
37
+ type?: "feature" | "bugfix" | "refactor" | "spike" | "docs" | "architecture" | "all" | undefined;
38
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
39
+ };
40
+ export declare const load: {
41
+ description: string;
42
+ args: {
43
+ filename: import("zod").ZodString;
44
+ };
45
+ execute(args: {
46
+ filename: string;
47
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
48
+ };
49
+ export declare const delete_: {
50
+ description: string;
51
+ args: {
52
+ filename: import("zod").ZodString;
53
+ };
54
+ execute(args: {
55
+ filename: string;
56
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
57
+ };
58
+ export { delete_ as delete };
59
+ //# sourceMappingURL=plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/tools/plan.ts"],"names":[],"mappings":"AAgCA,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;CA2Df,CAAC;AAEH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;CAkEf,CAAC;AAEH,eAAO,MAAM,IAAI;;;;;;;;CAuBf,CAAC;AAEH,eAAO,MAAM,OAAO;;;;;;;;CAkBlB,CAAC;AAGH,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,CAAC"}
@@ -0,0 +1,177 @@
1
+ import { tool } from "@opencode-ai/plugin";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ const CORTEX_DIR = ".cortex";
5
+ const PLANS_DIR = "plans";
6
+ function slugify(text) {
7
+ return text
8
+ .toLowerCase()
9
+ .replace(/[^\w\s-]/g, "")
10
+ .replace(/\s+/g, "-")
11
+ .replace(/-+/g, "-")
12
+ .substring(0, 50);
13
+ }
14
+ function getDatePrefix() {
15
+ const now = new Date();
16
+ return now.toISOString().split("T")[0]; // YYYY-MM-DD
17
+ }
18
+ function ensureCortexDir(worktree) {
19
+ const cortexPath = path.join(worktree, CORTEX_DIR);
20
+ const plansPath = path.join(cortexPath, PLANS_DIR);
21
+ if (!fs.existsSync(plansPath)) {
22
+ fs.mkdirSync(plansPath, { recursive: true });
23
+ }
24
+ return plansPath;
25
+ }
26
+ export const save = tool({
27
+ description: "Save an implementation plan to .cortex/plans/ with mermaid diagram support",
28
+ args: {
29
+ title: tool.schema.string().describe("Plan title (e.g., 'User Authentication System')"),
30
+ type: tool.schema
31
+ .enum(["feature", "bugfix", "refactor", "architecture", "spike", "docs"])
32
+ .describe("Plan type"),
33
+ content: tool.schema
34
+ .string()
35
+ .describe("Full plan content in markdown (can include mermaid diagrams)"),
36
+ tasks: tool.schema
37
+ .array(tool.schema.string())
38
+ .optional()
39
+ .describe("Optional list of tasks"),
40
+ },
41
+ async execute(args, context) {
42
+ const { title, type, content, tasks } = args;
43
+ const plansPath = ensureCortexDir(context.worktree);
44
+ const datePrefix = getDatePrefix();
45
+ const slug = slugify(title);
46
+ const filename = `${datePrefix}-${type}-${slug}.md`;
47
+ const filepath = path.join(plansPath, filename);
48
+ // Build frontmatter
49
+ const frontmatter = `---
50
+ title: "${title}"
51
+ type: ${type}
52
+ created: ${new Date().toISOString()}
53
+ status: draft
54
+ ---
55
+
56
+ `;
57
+ // Build task list if provided
58
+ let taskSection = "";
59
+ if (tasks && tasks.length > 0) {
60
+ taskSection = `\n## Tasks\n\n${tasks.map((t) => `- [ ] ${t}`).join("\n")}\n`;
61
+ }
62
+ // Combine content
63
+ const fullContent = frontmatter + `# ${title}\n\n` + content + taskSection;
64
+ // Write file
65
+ fs.writeFileSync(filepath, fullContent);
66
+ return `✓ Plan saved successfully
67
+
68
+ File: ${filename}
69
+ Path: ${filepath}
70
+
71
+ The plan includes:
72
+ - Title: ${title}
73
+ - Type: ${type}
74
+ - Tasks: ${tasks?.length || 0}
75
+
76
+ You can load this plan later with plan_load or view all plans with plan_list.`;
77
+ },
78
+ });
79
+ export const list = tool({
80
+ description: "List all saved plans in .cortex/plans/",
81
+ args: {
82
+ type: tool.schema
83
+ .enum(["feature", "bugfix", "refactor", "architecture", "spike", "docs", "all"])
84
+ .optional()
85
+ .describe("Filter by plan type (default: all)"),
86
+ },
87
+ async execute(args, context) {
88
+ const { type = "all" } = args;
89
+ const plansPath = path.join(context.worktree, CORTEX_DIR, PLANS_DIR);
90
+ if (!fs.existsSync(plansPath)) {
91
+ return `No plans found. The .cortex/plans/ directory doesn't exist.
92
+
93
+ Use plan_save to create your first plan, or cortex_init to initialize the directory.`;
94
+ }
95
+ const files = fs
96
+ .readdirSync(plansPath)
97
+ .filter((f) => f.endsWith(".md") && f !== ".gitkeep")
98
+ .sort()
99
+ .reverse();
100
+ if (files.length === 0) {
101
+ return "No plans found in .cortex/plans/";
102
+ }
103
+ let output = "📋 Saved Plans:\n\n";
104
+ for (const file of files) {
105
+ const filepath = path.join(plansPath, file);
106
+ const content = fs.readFileSync(filepath, "utf-8");
107
+ // Parse frontmatter
108
+ let title = file;
109
+ let planType = "unknown";
110
+ let created = "";
111
+ let status = "draft";
112
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
113
+ if (frontmatterMatch) {
114
+ const fm = frontmatterMatch[1];
115
+ const titleMatch = fm.match(/title:\s*"?([^"\n]+)"?/);
116
+ const typeMatch = fm.match(/type:\s*(\w+)/);
117
+ const createdMatch = fm.match(/created:\s*(\S+)/);
118
+ const statusMatch = fm.match(/status:\s*(\w+)/);
119
+ if (titleMatch)
120
+ title = titleMatch[1];
121
+ if (typeMatch)
122
+ planType = typeMatch[1];
123
+ if (createdMatch)
124
+ created = createdMatch[1].split("T")[0];
125
+ if (statusMatch)
126
+ status = statusMatch[1];
127
+ }
128
+ // Filter by type if specified
129
+ if (type !== "all" && planType !== type) {
130
+ continue;
131
+ }
132
+ output += `• ${title}\n`;
133
+ output += ` File: ${file}\n`;
134
+ output += ` Type: ${planType} | Created: ${created} | Status: ${status}\n\n`;
135
+ }
136
+ return output.trim();
137
+ },
138
+ });
139
+ export const load = tool({
140
+ description: "Load a saved plan by filename",
141
+ args: {
142
+ filename: tool.schema.string().describe("Plan filename (e.g., '2024-02-22-feature-auth.md')"),
143
+ },
144
+ async execute(args, context) {
145
+ const { filename } = args;
146
+ const plansPath = path.join(context.worktree, CORTEX_DIR, PLANS_DIR);
147
+ const filepath = path.join(plansPath, filename);
148
+ if (!fs.existsSync(filepath)) {
149
+ return `✗ Plan not found: ${filename}
150
+
151
+ Use plan_list to see available plans.`;
152
+ }
153
+ const content = fs.readFileSync(filepath, "utf-8");
154
+ return `📋 Plan: ${filename}
155
+ ${"=".repeat(50)}
156
+
157
+ ${content}`;
158
+ },
159
+ });
160
+ export const delete_ = tool({
161
+ description: "Delete a saved plan",
162
+ args: {
163
+ filename: tool.schema.string().describe("Plan filename to delete"),
164
+ },
165
+ async execute(args, context) {
166
+ const { filename } = args;
167
+ const plansPath = path.join(context.worktree, CORTEX_DIR, PLANS_DIR);
168
+ const filepath = path.join(plansPath, filename);
169
+ if (!fs.existsSync(filepath)) {
170
+ return `✗ Plan not found: ${filename}`;
171
+ }
172
+ fs.unlinkSync(filepath);
173
+ return `✓ Deleted plan: ${filename}`;
174
+ },
175
+ });
176
+ // Export with underscore suffix to avoid reserved word
177
+ export { delete_ as delete };
@@ -0,0 +1,36 @@
1
+ export declare const save: {
2
+ description: string;
3
+ args: {
4
+ summary: import("zod").ZodString;
5
+ decisions: import("zod").ZodArray<import("zod").ZodString>;
6
+ filesChanged: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
7
+ relatedPlan: import("zod").ZodOptional<import("zod").ZodString>;
8
+ branch: import("zod").ZodOptional<import("zod").ZodString>;
9
+ };
10
+ execute(args: {
11
+ summary: string;
12
+ decisions: string[];
13
+ filesChanged?: string[] | undefined;
14
+ relatedPlan?: string | undefined;
15
+ branch?: string | undefined;
16
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
17
+ };
18
+ export declare const list: {
19
+ description: string;
20
+ args: {
21
+ limit: import("zod").ZodOptional<import("zod").ZodNumber>;
22
+ };
23
+ execute(args: {
24
+ limit?: number | undefined;
25
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
26
+ };
27
+ export declare const load: {
28
+ description: string;
29
+ args: {
30
+ filename: import("zod").ZodString;
31
+ };
32
+ execute(args: {
33
+ filename: string;
34
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
35
+ };
36
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/tools/session.ts"],"names":[],"mappings":"AA2BA,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;CAsFf,CAAC;AAEH,eAAO,MAAM,IAAI;;;;;;;;CA8Df,CAAC;AAEH,eAAO,MAAM,IAAI;;;;;;;;CAuBf,CAAC"}