whipped 0.1.1 → 0.2.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.
package/README.md CHANGED
@@ -194,7 +194,7 @@ Whipped can start a [Cloudflare Tunnel](https://developers.cloudflare.com/cloudf
194
194
 
195
195
  A standalone Chrome/Chromium extension for capturing UI context off any web page. Click the toolbar icon to enter select mode, then click any element to capture its React component and source location. It builds a ready-to-paste **YAML prompt** for your AI coding agent — no server connection required.
196
196
 
197
- Available at [github.com/nxnom/whipped-extension](https://github.com/nxnom/whipped-extension).
197
+ Install from the [Chrome Web Store](https://chromewebstore.google.com/detail/codkafoociihebdklkpfjjoacenkkhci?utm_source=item-share-cb), or build from source at [github.com/nxnom/whipped-extension](https://github.com/nxnom/whipped-extension).
198
198
 
199
199
  ### Visual comments
200
200
 
package/dist/cli.js CHANGED
@@ -18966,6 +18966,7 @@ function isCommandAvailable(args) {
18966
18966
  stdio: ["ignore", "pipe", "ignore"],
18967
18967
  timeout: 5e3
18968
18968
  });
18969
+ if (result.error) return result.error.code !== "ENOENT";
18969
18970
  return result.status === 0 || result.status === null;
18970
18971
  }
18971
18972
  function getAvailableAgents() {
@@ -22530,10 +22531,11 @@ ${devSystemPromptResult.text}`;
22530
22531
  const conflictGitInstructions = conflictProjectConfig.gitInstructions?.trim() || DEFAULT_GIT_INSTRUCTIONS;
22531
22532
  let outputBuffer = "";
22532
22533
  let hookHandled = false;
22534
+ const conflictSystemPrompt = buildConflictResolutionSystemPrompt(card, conflictedFiles, conflictGitInstructions);
22533
22535
  if (defaultAgent === "opencode") {
22534
22536
  const mcpSpec = buildWhippedMcpServerSpec(getMcpServerPath(), this.options.serverUrl, workspaceId);
22535
22537
  await writeOpencodeFiles(streamId, getServerPort(this.options.serverUrl), mcpSpec, {
22536
- appendSystemPrompt: CONFLICT_RESOLUTION_SYSTEM_PROMPT
22538
+ appendSystemPrompt: conflictSystemPrompt
22537
22539
  }).catch(() => {
22538
22540
  });
22539
22541
  } else if (defaultAgent === "cursor") {
@@ -22543,7 +22545,7 @@ ${devSystemPromptResult.text}`;
22543
22545
  }
22544
22546
  const proc = spawnAgent({
22545
22547
  agentId: defaultAgent,
22546
- prompt: buildConflictResolutionPrompt(card, conflictedFiles, conflictGitInstructions),
22548
+ prompt: buildTaskPrompt(),
22547
22549
  cwd: mergeWorktreePath,
22548
22550
  hookSettingsPath: defaultAgent === "claude" ? CLAUDE_TASK_SETTINGS_PATH : void 0,
22549
22551
  hookServerPort: defaultAgent === "codex" ? getServerPort(this.options.serverUrl) : void 0,
@@ -22552,7 +22554,7 @@ ${devSystemPromptResult.text}`;
22552
22554
  ...defaultAgent === "opencode" ? { [OPENCODE_CONFIG_DIR_ENV]: getOpencodeConfigDir(streamId) } : {},
22553
22555
  ...defaultAgent === "cursor" ? { [CURSOR_CONFIG_DIR_ENV]: getCursorConfigDir(streamId) } : {}
22554
22556
  },
22555
- appendSystemPrompt: defaultAgent !== "opencode" ? CONFLICT_RESOLUTION_SYSTEM_PROMPT : void 0,
22557
+ appendSystemPrompt: defaultAgent !== "opencode" ? conflictSystemPrompt : void 0,
22556
22558
  onOutput: (data) => {
22557
22559
  outputBuffer += data;
22558
22560
  stateHub.broadcastTerminalOutput(workspaceId, streamId, data);
@@ -22714,27 +22716,27 @@ ${secretsSection}` : ""}${systemPrompt?.trim() ? `
22714
22716
 
22715
22717
  ${systemPrompt.trim()}` : ""}`;
22716
22718
  }
22717
- var CONFLICT_RESOLUTION_SYSTEM_PROMPT = `You are a merge conflict resolution agent. Your only job is to resolve git merge conflicts.
22719
+ function buildConflictResolutionSystemPrompt(card, conflictedFiles, gitInstructions) {
22720
+ return `You are a merge conflict resolution agent. Your only job is to resolve git merge conflicts.
22718
22721
 
22719
22722
  Rules:
22720
22723
  - Only edit files to remove conflict markers (<<<<<<< ======= >>>>>>>)
22721
22724
  - Preserve the intent of BOTH sides where possible; when in doubt keep the incoming (task) changes
22722
22725
  - Never refactor, rename, or change logic beyond resolving the conflict markers
22723
- - Exit when done`;
22724
- function buildConflictResolutionPrompt(card, conflictedFiles, gitInstructions) {
22725
- return `Resolve the git merge conflicts in this repository.
22726
+ - Exit when done
22727
+
22728
+ ## Task being merged
22726
22729
 
22727
- Task being merged:
22728
22730
  ${card.description?.trim() ?? ""}
22729
22731
 
22730
- Conflicted files:
22732
+ ## Conflicted files
22733
+
22731
22734
  ${conflictedFiles.map((f2) => `- ${f2}`).join("\n")}
22732
22735
 
22733
- Resolve each conflict, preserving the task's intent. Then stage and commit
22734
- the resolution. Write the commit message following the project's git
22735
- conventions below \u2014 do not use a hard-coded template.
22736
+ Resolve each conflict, preserving the task's intent. Then stage and commit the resolution. Write the commit message following the project's git conventions below \u2014 do not use a hard-coded template.
22736
22737
 
22737
22738
  ## Git conventions
22739
+
22738
22740
  ${gitInstructions}`;
22739
22741
  }
22740
22742
  function buildTaskPrompt() {
@@ -26831,8 +26833,8 @@ import { z as z9 } from "zod";
26831
26833
  // src/api/services/projects-service.ts
26832
26834
  init_runtime_config();
26833
26835
  init_api_contract();
26834
- init_logger();
26835
26836
  import { spawnSync as spawnSync9 } from "node:child_process";
26837
+ init_logger();
26836
26838
 
26837
26839
  // src/state/projects-layout.ts
26838
26840
  init_db();
@@ -26888,14 +26890,31 @@ var saveProjectsLayoutData = (layout) => {
26888
26890
  return { ok: true };
26889
26891
  };
26890
26892
  var checkProjectPath = async (repoPath) => {
26891
- if (!repoPath.trim()) return { valid: false, isGitRepo: false, error: null, name: null, branch: null, remote: null };
26893
+ if (!repoPath.trim())
26894
+ return { valid: false, isGitRepo: false, error: null, name: null, branch: null, remote: null, branches: [] };
26892
26895
  const { statSync: statSync2 } = await import("node:fs");
26893
26896
  try {
26894
26897
  const stat2 = statSync2(repoPath);
26895
26898
  if (!stat2.isDirectory())
26896
- return { valid: false, isGitRepo: false, error: "Not a directory", name: null, branch: null, remote: null };
26899
+ return {
26900
+ valid: false,
26901
+ isGitRepo: false,
26902
+ error: "Not a directory",
26903
+ name: null,
26904
+ branch: null,
26905
+ remote: null,
26906
+ branches: []
26907
+ };
26897
26908
  } catch {
26898
- return { valid: false, isGitRepo: false, error: "Path does not exist", name: null, branch: null, remote: null };
26909
+ return {
26910
+ valid: false,
26911
+ isGitRepo: false,
26912
+ error: "Path does not exist",
26913
+ name: null,
26914
+ branch: null,
26915
+ remote: null,
26916
+ branches: []
26917
+ };
26899
26918
  }
26900
26919
  const r = spawnSync9("git", ["rev-parse", "--git-dir"], {
26901
26920
  cwd: repoPath,
@@ -26910,7 +26929,8 @@ var checkProjectPath = async (repoPath) => {
26910
26929
  error: "Not a git repository",
26911
26930
  name: null,
26912
26931
  branch: null,
26913
- remote: null
26932
+ remote: null,
26933
+ branches: []
26914
26934
  };
26915
26935
  const branchR = spawnSync9("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
26916
26936
  cwd: repoPath,
@@ -26926,7 +26946,7 @@ var checkProjectPath = async (repoPath) => {
26926
26946
  const branch = branchR.status === 0 ? branchR.stdout.trim() : null;
26927
26947
  const rawRemote = remoteR.status === 0 ? remoteR.stdout.trim() : null;
26928
26948
  const remote = rawRemote ? rawRemote.replace(/^https?:\/\//, "").replace(/^git@([^:]+):/, "$1/").replace(/\.git$/, "") : null;
26929
- return { valid: true, isGitRepo: true, error: null, name, branch, remote };
26949
+ return { valid: true, isGitRepo: true, error: null, name, branch, remote, branches: listLocalBranches(repoPath) };
26930
26950
  };
26931
26951
  var addProject = async (repoPath, initialConfig) => {
26932
26952
  const { statSync: statSync2 } = await import("node:fs");
@@ -28545,7 +28565,7 @@ process.on("uncaughtException", (err) => {
28545
28565
  if (err.code === "EPIPE" || err.code === "ECONNRESET") return;
28546
28566
  throw err;
28547
28567
  });
28548
- var VERSION9 = true ? "0.1.1" : "0.0.0-dev";
28568
+ var VERSION9 = true ? "0.2.0" : "0.0.0-dev";
28549
28569
  async function isPortAvailable(port, host) {
28550
28570
  return new Promise((resolve5) => {
28551
28571
  const probe = createServer2();