vibeman 0.0.16 → 0.0.17
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/dist/api.js +506 -82
- package/dist/commit.txt +1 -1
- package/dist/ui/assets/{index-CkMEKMtG.js → index-B0WvXt0J.js} +1 -1
- package/dist/ui/assets/index-B1LpYbIL.css +1 -0
- package/dist/ui/assets/{index-DRYG0hWl.js → index-B9j1Z7xH.js} +1 -1
- package/dist/ui/assets/index-BGSXwEof.js +1103 -0
- package/dist/ui/assets/{index-DJxs2IHl.js → index-BMvqb2S0.js} +1 -1
- package/dist/ui/assets/{index-Db2EhJOX.js → index-BaTjy202.js} +1 -1
- package/dist/ui/assets/{index-Dck1mk1E.js → index-Bf-sg7t1.js} +1 -1
- package/dist/ui/assets/{index-ssu5S1KA.js → index-BjP484xW.js} +1 -1
- package/dist/ui/assets/{index-mhz4dktY.js → index-CHaxebS-.js} +1 -1
- package/dist/ui/assets/{index-DARaaYLg.js → index-CM8fvy_3.js} +1 -1
- package/dist/ui/assets/{index-DErcnUD0.js → index-CgPm7uHs.js} +1 -1
- package/dist/ui/assets/{index-b2CKrEE6.js → index-CgR7ieU_.js} +1 -1
- package/dist/ui/assets/{index-DKTHpT6c.js → index-CmRfv-pq.js} +1 -1
- package/dist/ui/assets/{index-CnWjvgnt.js → index-DJPvnRwe.js} +1 -1
- package/dist/ui/assets/{index-DPgndyQt.js → index-DVUZnv4I.js} +1 -1
- package/dist/ui/assets/{index-B77m9jwg.js → index-DWOryZN1.js} +1 -1
- package/dist/ui/assets/{index-CpEU6Vxs.js → index-DhCgwoTQ.js} +1 -1
- package/dist/ui/assets/{index-B49cVd68.js → index-Dl7WFkDL.js} +1 -1
- package/dist/ui/assets/{index-C61bzN1F.js → index-DxYZT2Q7.js} +1 -1
- package/dist/ui/assets/{index-CHinfK5y.js → index-JyRtNGro.js} +1 -1
- package/dist/ui/assets/{index-Cl5D1lr0.js → index-RO6e7ud2.js} +1 -1
- package/dist/ui/assets/{index-CdwIPvvC.js → index-dZUCDdRl.js} +1 -1
- package/dist/ui/assets/{index-D_--wkOk.js → index-h0c542Uj.js} +1 -1
- package/dist/ui/assets/{index-D6YdKIji.js → index-qhLd2sra.js} +1 -1
- package/dist/ui/assets/vibeman-logo-on-dark-GVk_1Rmr.png +0 -0
- package/dist/ui/assets/vibeman-logo-on-light-4VCHa-wB.png +0 -0
- package/dist/ui/index.html +5 -2
- package/dist/ui/vibeman-apple-touch-icon.png +0 -0
- package/dist/ui/vibeman-favicon-16.png +0 -0
- package/dist/ui/vibeman-favicon-32.png +0 -0
- package/package.json +1 -1
- package/dist/ui/assets/index-CEeUnKFj.js +0 -1101
- package/dist/ui/assets/index-DcDF1o3A.css +0 -1
package/dist/api.js
CHANGED
|
@@ -54569,22 +54569,18 @@ async function getRepoDirtyBeforeWorktreeCreateMessage(repoRoot, worktreePath, g
|
|
|
54569
54569
|
}
|
|
54570
54570
|
const { branch, lines, suffix } = await readGitStatusDetails(gitService);
|
|
54571
54571
|
return [
|
|
54572
|
-
"Cannot create a new task worktree
|
|
54572
|
+
"Cannot create a new task worktree while the repository root has uncommitted changes.",
|
|
54573
54573
|
"",
|
|
54574
|
-
"
|
|
54575
|
-
"A new worktree starts from the latest committed state. Uncommitted changes in the main repository are not copied into the new worktree, so it would open with stale code.",
|
|
54574
|
+
"A new worktree starts from the latest committed state. Any uncommitted repository root changes would be missing from the new task worktree.",
|
|
54576
54575
|
"",
|
|
54577
|
-
"
|
|
54578
|
-
"
|
|
54579
|
-
"
|
|
54580
|
-
"- Discard them if they are no longer needed.",
|
|
54576
|
+
"Use the header Commit Changes button to review and commit the repository root changes.",
|
|
54577
|
+
"If you are not ready to commit, stash or discard the root changes first.",
|
|
54578
|
+
"Retry creating the worktree after the repository root is clean.",
|
|
54581
54579
|
"",
|
|
54582
|
-
"Then try creating the worktree again.",
|
|
54583
|
-
"",
|
|
54584
|
-
`Planned worktree:
|
|
54585
|
-
${worktreePath}`,
|
|
54586
54580
|
`Repository root:
|
|
54587
54581
|
${repoRoot}`,
|
|
54582
|
+
`Planned worktree:
|
|
54583
|
+
${worktreePath}`,
|
|
54588
54584
|
`Branch:
|
|
54589
54585
|
${branch}`,
|
|
54590
54586
|
`Changes:
|
|
@@ -55694,6 +55690,7 @@ async function listLatestTaskWorkflowStatusByTaskId(db, taskIds) {
|
|
|
55694
55690
|
taskId,
|
|
55695
55691
|
workflowType,
|
|
55696
55692
|
status,
|
|
55693
|
+
updatedAt,
|
|
55697
55694
|
ROW_NUMBER() OVER (
|
|
55698
55695
|
PARTITION BY taskId, workflowType
|
|
55699
55696
|
ORDER BY updatedAt DESC, createdAt DESC, runId DESC
|
|
@@ -55703,7 +55700,7 @@ async function listLatestTaskWorkflowStatusByTaskId(db, taskIds) {
|
|
|
55703
55700
|
AND taskId <> ''
|
|
55704
55701
|
${taskFilterSql}
|
|
55705
55702
|
)
|
|
55706
|
-
SELECT taskId, workflowType, status
|
|
55703
|
+
SELECT taskId, workflowType, status, updatedAt
|
|
55707
55704
|
FROM ranked_runs
|
|
55708
55705
|
WHERE rownum = 1
|
|
55709
55706
|
ORDER BY taskId ASC, workflowType ASC
|
|
@@ -55723,7 +55720,8 @@ async function listLatestTaskWorkflowStatusByTaskId(db, taskIds) {
|
|
|
55723
55720
|
}
|
|
55724
55721
|
statusByTaskId[row.taskId]?.push({
|
|
55725
55722
|
workflowType,
|
|
55726
|
-
status
|
|
55723
|
+
status,
|
|
55724
|
+
updatedAt: row.updatedAt instanceof Date ? row.updatedAt.toISOString() : String(row.updatedAt)
|
|
55727
55725
|
});
|
|
55728
55726
|
}
|
|
55729
55727
|
for (const taskId of Object.keys(statusByTaskId)) {
|
|
@@ -59532,9 +59530,10 @@ var init_model_aliases = __esm(() => {
|
|
|
59532
59530
|
});
|
|
59533
59531
|
|
|
59534
59532
|
// ../api/src/services/agents/runtime-backend.ts
|
|
59535
|
-
import {
|
|
59533
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
59534
|
+
import { mkdir as mkdir2, lstat, readdir as readdir2, readlink, rm, symlink } from "node:fs/promises";
|
|
59536
59535
|
import { tmpdir } from "node:os";
|
|
59537
|
-
import { join as join4 } from "node:path";
|
|
59536
|
+
import { dirname as dirname4, join as join4, resolve as resolvePath4 } from "node:path";
|
|
59538
59537
|
function isPlainObject4(value) {
|
|
59539
59538
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
59540
59539
|
}
|
|
@@ -59793,6 +59792,45 @@ async function applyClaudeRuntimeIsolation(request, env) {
|
|
|
59793
59792
|
XDG_DATA_HOME: xdgDataHome
|
|
59794
59793
|
};
|
|
59795
59794
|
}
|
|
59795
|
+
function resolveCodexHome(env) {
|
|
59796
|
+
const configured = env.CODEX_HOME?.trim();
|
|
59797
|
+
if (configured) {
|
|
59798
|
+
return resolvePath4(configured);
|
|
59799
|
+
}
|
|
59800
|
+
const home = env.HOME?.trim();
|
|
59801
|
+
if (!home) {
|
|
59802
|
+
return;
|
|
59803
|
+
}
|
|
59804
|
+
return resolvePath4(home, ".codex");
|
|
59805
|
+
}
|
|
59806
|
+
async function ensureSymlinkTarget(targetPath, sourcePath) {
|
|
59807
|
+
try {
|
|
59808
|
+
const stats = await lstat(targetPath);
|
|
59809
|
+
if (stats.isSymbolicLink()) {
|
|
59810
|
+
const existingTarget = await readlink(targetPath);
|
|
59811
|
+
if (resolvePath4(dirname4(targetPath), existingTarget) === resolvePath4(sourcePath)) {
|
|
59812
|
+
return;
|
|
59813
|
+
}
|
|
59814
|
+
}
|
|
59815
|
+
await rm(targetPath, { recursive: true, force: true });
|
|
59816
|
+
} catch {}
|
|
59817
|
+
await symlink(sourcePath, targetPath);
|
|
59818
|
+
}
|
|
59819
|
+
async function applyCodexRuntimeIsolation(request, env) {
|
|
59820
|
+
const sourceCodexHome = resolveCodexHome(env);
|
|
59821
|
+
if (!sourceCodexHome || !existsSync13(sourceCodexHome)) {
|
|
59822
|
+
return env;
|
|
59823
|
+
}
|
|
59824
|
+
const runId = toSafePathSegment(request.runId);
|
|
59825
|
+
const isolationRoot = join4(tmpdir(), "vibeman", "runtime", "runs", runId, "codex-home");
|
|
59826
|
+
await mkdir2(isolationRoot, { recursive: true });
|
|
59827
|
+
const entries = await readdir2(sourceCodexHome, { withFileTypes: true });
|
|
59828
|
+
await Promise.all(entries.filter((entry) => entry.name !== "superpowers").map((entry) => ensureSymlinkTarget(join4(isolationRoot, entry.name), join4(sourceCodexHome, entry.name))));
|
|
59829
|
+
return {
|
|
59830
|
+
...env,
|
|
59831
|
+
CODEX_HOME: isolationRoot
|
|
59832
|
+
};
|
|
59833
|
+
}
|
|
59796
59834
|
function shouldIsolateClaudeRuntime(env) {
|
|
59797
59835
|
const anthropicAuthToken = env.ANTHROPIC_AUTH_TOKEN?.trim();
|
|
59798
59836
|
const anthropicApiKey = env.ANTHROPIC_API_KEY?.trim();
|
|
@@ -59865,6 +59903,9 @@ async function compileAgentExecutionPlan(db, request) {
|
|
|
59865
59903
|
...resolvedLegacyEnv,
|
|
59866
59904
|
...resolvedOverrideEnv
|
|
59867
59905
|
};
|
|
59906
|
+
if (provider === "codex-cli") {
|
|
59907
|
+
env = await applyCodexRuntimeIsolation(request, env);
|
|
59908
|
+
}
|
|
59868
59909
|
if (provider === "claude-code" && shouldIsolateClaudeRuntime(env)) {
|
|
59869
59910
|
env = await applyClaudeRuntimeIsolation(request, env);
|
|
59870
59911
|
}
|
|
@@ -60082,22 +60123,22 @@ var init_agents = __esm(() => {
|
|
|
60082
60123
|
|
|
60083
60124
|
// ../api/src/services/env-symlinks.ts
|
|
60084
60125
|
import { spawnSync } from "node:child_process";
|
|
60085
|
-
import { existsSync as
|
|
60086
|
-
import { lstat, readlink, readdir as
|
|
60087
|
-
import { dirname as
|
|
60126
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
60127
|
+
import { lstat as lstat2, readlink as readlink2, readdir as readdir3, symlink as symlink2 } from "node:fs/promises";
|
|
60128
|
+
import { dirname as dirname5, normalize as normalize5, resolve as resolve12 } from "node:path";
|
|
60088
60129
|
async function ensureEnvSymlinks(options2) {
|
|
60089
60130
|
const log = logger.child({ module: "env-symlinks", ...options2.logContext });
|
|
60090
|
-
if (!
|
|
60131
|
+
if (!existsSync14(options2.repoRoot)) {
|
|
60091
60132
|
log.warn({ repoRoot: options2.repoRoot }, "Repo root does not exist; skipping env symlinks.");
|
|
60092
60133
|
return;
|
|
60093
60134
|
}
|
|
60094
|
-
if (!
|
|
60135
|
+
if (!existsSync14(options2.targetRoot)) {
|
|
60095
60136
|
log.warn({ targetRoot: options2.targetRoot }, "Target root does not exist; skipping env symlinks.");
|
|
60096
60137
|
return;
|
|
60097
60138
|
}
|
|
60098
60139
|
let entries;
|
|
60099
60140
|
try {
|
|
60100
|
-
entries = await
|
|
60141
|
+
entries = await readdir3(options2.repoRoot);
|
|
60101
60142
|
} catch (error48) {
|
|
60102
60143
|
log.warn({ error: error48 }, "Failed to read repo root for env symlinks.");
|
|
60103
60144
|
return;
|
|
@@ -60116,7 +60157,7 @@ async function ensureEnvSymlinks(options2) {
|
|
|
60116
60157
|
const sourcePath = resolve12(options2.repoRoot, name2);
|
|
60117
60158
|
const targetPath = resolve12(options2.targetRoot, name2);
|
|
60118
60159
|
try {
|
|
60119
|
-
const sourceStat = await
|
|
60160
|
+
const sourceStat = await lstat2(sourcePath);
|
|
60120
60161
|
if (!sourceStat.isFile()) {
|
|
60121
60162
|
log.info({ file: name2 }, "Skipping env entry that is not a regular file.");
|
|
60122
60163
|
continue;
|
|
@@ -60140,10 +60181,10 @@ function isGitIgnored(repoRoot, relativePath, log) {
|
|
|
60140
60181
|
}
|
|
60141
60182
|
async function ensureSymlink(sourcePath, targetPath, log, filename) {
|
|
60142
60183
|
try {
|
|
60143
|
-
const existing = await
|
|
60184
|
+
const existing = await lstat2(targetPath);
|
|
60144
60185
|
if (existing.isSymbolicLink()) {
|
|
60145
|
-
const linkTarget = await
|
|
60146
|
-
const resolvedTarget = normalize5(resolve12(
|
|
60186
|
+
const linkTarget = await readlink2(targetPath);
|
|
60187
|
+
const resolvedTarget = normalize5(resolve12(dirname5(targetPath), linkTarget));
|
|
60147
60188
|
const resolvedSource = normalize5(resolve12(sourcePath));
|
|
60148
60189
|
if (resolvedTarget === resolvedSource) {
|
|
60149
60190
|
return;
|
|
@@ -60160,7 +60201,7 @@ async function ensureSymlink(sourcePath, targetPath, log, filename) {
|
|
|
60160
60201
|
}
|
|
60161
60202
|
}
|
|
60162
60203
|
try {
|
|
60163
|
-
await
|
|
60204
|
+
await symlink2(sourcePath, targetPath, "file");
|
|
60164
60205
|
} catch (error48) {
|
|
60165
60206
|
log.warn({ error: error48, file: filename, target: targetPath }, "Failed to create env symlink.");
|
|
60166
60207
|
}
|
|
@@ -102232,7 +102273,7 @@ var init_prompt_builder = __esm(() => {
|
|
|
102232
102273
|
// ../api/src/services/workflows/executor.ts
|
|
102233
102274
|
import { spawn as spawn5 } from "node:child_process";
|
|
102234
102275
|
import { readFileSync as readFileSync4 } from "node:fs";
|
|
102235
|
-
import { resolve as
|
|
102276
|
+
import { resolve as resolvePath5 } from "node:path";
|
|
102236
102277
|
function createExecutorControl() {
|
|
102237
102278
|
const abortController = new AbortController;
|
|
102238
102279
|
let child = null;
|
|
@@ -103132,7 +103173,7 @@ function normalizeEnvPath(raw2) {
|
|
|
103132
103173
|
const trimmed2 = raw2.trim();
|
|
103133
103174
|
if (trimmed2.length === 0)
|
|
103134
103175
|
return null;
|
|
103135
|
-
return
|
|
103176
|
+
return resolvePath5(trimmed2);
|
|
103136
103177
|
}
|
|
103137
103178
|
function summarizeShellFailure(command, result) {
|
|
103138
103179
|
const SNIPPET_LINES = 30;
|
|
@@ -107968,10 +108009,11 @@ var init_remote_access = __esm(() => {
|
|
|
107968
108009
|
});
|
|
107969
108010
|
|
|
107970
108011
|
// ../api/src/server/routes/system.ts
|
|
107971
|
-
import { spawn as spawn7 } from "node:child_process";
|
|
107972
|
-
import { resolve as resolve18, relative as relative7, sep as sep3 } from "node:path";
|
|
107973
|
-
import { access as access3 } from "node:fs/promises";
|
|
107974
|
-
import { homedir as homedir2 } from "node:os";
|
|
108012
|
+
import { execFile as execFile5, spawn as spawn7 } from "node:child_process";
|
|
108013
|
+
import { resolve as resolve18, relative as relative7, sep as sep3, join as join6, extname } from "node:path";
|
|
108014
|
+
import { access as access3, mkdtemp, readFile as readFile6, rm as rm2 } from "node:fs/promises";
|
|
108015
|
+
import { homedir as homedir2, tmpdir as tmpdir2 } from "node:os";
|
|
108016
|
+
import { promisify as promisify2 } from "node:util";
|
|
107975
108017
|
function isWithin2(rootPath, targetPath) {
|
|
107976
108018
|
const relativePath = relative7(rootPath, targetPath);
|
|
107977
108019
|
return relativePath === "" || !relativePath.startsWith("..") && !relativePath.startsWith(`..${sep3}`);
|
|
@@ -108003,11 +108045,108 @@ async function isAnyDetectionPathAccessible(paths) {
|
|
|
108003
108045
|
}
|
|
108004
108046
|
return false;
|
|
108005
108047
|
}
|
|
108048
|
+
async function resolveAccessibleDetectionPath(paths) {
|
|
108049
|
+
for (const rawPath of paths) {
|
|
108050
|
+
const candidate = resolveDetectionPath(rawPath);
|
|
108051
|
+
try {
|
|
108052
|
+
await access3(candidate);
|
|
108053
|
+
return candidate;
|
|
108054
|
+
} catch {}
|
|
108055
|
+
}
|
|
108056
|
+
return null;
|
|
108057
|
+
}
|
|
108058
|
+
function normalizeIconFileName(value) {
|
|
108059
|
+
if (typeof value !== "string" || value.trim().length === 0)
|
|
108060
|
+
return null;
|
|
108061
|
+
const trimmed2 = value.trim();
|
|
108062
|
+
return extname(trimmed2) ? trimmed2 : `${trimmed2}.icns`;
|
|
108063
|
+
}
|
|
108064
|
+
function extractIconFileName(plist) {
|
|
108065
|
+
const directCandidates = [
|
|
108066
|
+
plist.CFBundleIconFile,
|
|
108067
|
+
plist.CFBundleIconName,
|
|
108068
|
+
plist.CFBundlePrimaryIcon?.CFBundleIconFile
|
|
108069
|
+
];
|
|
108070
|
+
for (const candidate of directCandidates) {
|
|
108071
|
+
const normalized = normalizeIconFileName(candidate);
|
|
108072
|
+
if (normalized)
|
|
108073
|
+
return normalized;
|
|
108074
|
+
}
|
|
108075
|
+
const bundleIcons = plist.CFBundleIcons;
|
|
108076
|
+
if (bundleIcons && typeof bundleIcons === "object") {
|
|
108077
|
+
const primaryIcon = bundleIcons.CFBundlePrimaryIcon;
|
|
108078
|
+
if (primaryIcon && typeof primaryIcon === "object") {
|
|
108079
|
+
const iconFiles = primaryIcon.CFBundleIconFiles;
|
|
108080
|
+
if (Array.isArray(iconFiles)) {
|
|
108081
|
+
for (const candidate of [...iconFiles].reverse()) {
|
|
108082
|
+
const normalized = normalizeIconFileName(candidate);
|
|
108083
|
+
if (normalized)
|
|
108084
|
+
return normalized;
|
|
108085
|
+
}
|
|
108086
|
+
}
|
|
108087
|
+
}
|
|
108088
|
+
}
|
|
108089
|
+
return null;
|
|
108090
|
+
}
|
|
108091
|
+
function toDataUrl(buffer, extension) {
|
|
108092
|
+
const normalized = extension.toLowerCase();
|
|
108093
|
+
if (normalized === ".svg") {
|
|
108094
|
+
return `data:image/svg+xml;base64,${buffer.toString("base64")}`;
|
|
108095
|
+
}
|
|
108096
|
+
if (normalized === ".jpg" || normalized === ".jpeg") {
|
|
108097
|
+
return `data:image/jpeg;base64,${buffer.toString("base64")}`;
|
|
108098
|
+
}
|
|
108099
|
+
return `data:image/png;base64,${buffer.toString("base64")}`;
|
|
108100
|
+
}
|
|
108101
|
+
async function convertIcnsToPngDataUrl(iconPath) {
|
|
108102
|
+
const tempDir = await mkdtemp(join6(tmpdir2(), "vibeman-app-icon-"));
|
|
108103
|
+
const pngPath = join6(tempDir, "icon.png");
|
|
108104
|
+
try {
|
|
108105
|
+
await execFileAsync2("sips", ["-s", "format", "png", iconPath, "--out", pngPath]);
|
|
108106
|
+
const pngBuffer = await readFile6(pngPath);
|
|
108107
|
+
return toDataUrl(pngBuffer, ".png");
|
|
108108
|
+
} finally {
|
|
108109
|
+
await rm2(tempDir, { recursive: true, force: true });
|
|
108110
|
+
}
|
|
108111
|
+
}
|
|
108112
|
+
async function readAppIconDataUrl(appPath) {
|
|
108113
|
+
const cached2 = appIconCache.get(appPath);
|
|
108114
|
+
if (cached2 !== undefined)
|
|
108115
|
+
return cached2;
|
|
108116
|
+
const infoPlistPath = join6(appPath, "Contents", "Info.plist");
|
|
108117
|
+
try {
|
|
108118
|
+
const { stdout } = await execFileAsync2("plutil", [
|
|
108119
|
+
"-convert",
|
|
108120
|
+
"json",
|
|
108121
|
+
"-o",
|
|
108122
|
+
"-",
|
|
108123
|
+
infoPlistPath
|
|
108124
|
+
]);
|
|
108125
|
+
const plist = JSON.parse(stdout);
|
|
108126
|
+
const iconFileName = extractIconFileName(plist);
|
|
108127
|
+
if (!iconFileName) {
|
|
108128
|
+
appIconCache.set(appPath, null);
|
|
108129
|
+
return null;
|
|
108130
|
+
}
|
|
108131
|
+
const iconPath = join6(appPath, "Contents", "Resources", iconFileName);
|
|
108132
|
+
await access3(iconPath);
|
|
108133
|
+
const extension = extname(iconPath).toLowerCase();
|
|
108134
|
+
const dataUrl = extension === ".icns" ? await convertIcnsToPngDataUrl(iconPath) : toDataUrl(await readFile6(iconPath), extension);
|
|
108135
|
+
appIconCache.set(appPath, dataUrl);
|
|
108136
|
+
return dataUrl;
|
|
108137
|
+
} catch {
|
|
108138
|
+
appIconCache.set(appPath, null);
|
|
108139
|
+
return null;
|
|
108140
|
+
}
|
|
108141
|
+
}
|
|
108006
108142
|
async function listAvailableApps(category) {
|
|
108007
108143
|
const defs = appCatalog.filter((app) => app.category === category);
|
|
108008
108144
|
const results = await Promise.all(defs.map(async (app) => {
|
|
108009
|
-
const
|
|
108010
|
-
|
|
108145
|
+
const installedPath = await resolveAccessibleDetectionPath(app.detectionPaths);
|
|
108146
|
+
if (!installedPath)
|
|
108147
|
+
return null;
|
|
108148
|
+
const iconDataUrl = await readAppIconDataUrl(installedPath);
|
|
108149
|
+
return { id: app.id, label: app.label, iconDataUrl };
|
|
108011
108150
|
}));
|
|
108012
108151
|
return results.filter(Boolean);
|
|
108013
108152
|
}
|
|
@@ -108059,7 +108198,7 @@ async function openInApp(appName, targetPath) {
|
|
|
108059
108198
|
});
|
|
108060
108199
|
});
|
|
108061
108200
|
}
|
|
108062
|
-
var appCategories, appCatalog, systemRouter;
|
|
108201
|
+
var appCategories, execFileAsync2, appIconCache, appCatalog, systemRouter;
|
|
108063
108202
|
var init_system2 = __esm(() => {
|
|
108064
108203
|
init_dist4();
|
|
108065
108204
|
init_zod();
|
|
@@ -108067,6 +108206,8 @@ var init_system2 = __esm(() => {
|
|
|
108067
108206
|
init_env_policy();
|
|
108068
108207
|
init_remote_access();
|
|
108069
108208
|
appCategories = ["terminal", "editor"];
|
|
108209
|
+
execFileAsync2 = promisify2(execFile5);
|
|
108210
|
+
appIconCache = new Map;
|
|
108070
108211
|
appCatalog = [
|
|
108071
108212
|
{
|
|
108072
108213
|
id: "warp",
|
|
@@ -108113,6 +108254,13 @@ var init_system2 = __esm(() => {
|
|
|
108113
108254
|
openAppName: "Antigravity",
|
|
108114
108255
|
detectionPaths: ["/Applications/Antigravity.app", "~/Applications/Antigravity.app"]
|
|
108115
108256
|
},
|
|
108257
|
+
{
|
|
108258
|
+
id: "zed",
|
|
108259
|
+
category: "editor",
|
|
108260
|
+
label: "Zed",
|
|
108261
|
+
openAppName: "Zed",
|
|
108262
|
+
detectionPaths: ["/Applications/Zed.app", "~/Applications/Zed.app"]
|
|
108263
|
+
},
|
|
108116
108264
|
{
|
|
108117
108265
|
id: "vscode",
|
|
108118
108266
|
category: "editor",
|
|
@@ -108310,7 +108458,7 @@ var init_system2 = __esm(() => {
|
|
|
108310
108458
|
|
|
108311
108459
|
// ../api/src/services/assets.ts
|
|
108312
108460
|
import { mkdir as mkdir4, writeFile as writeFile5 } from "node:fs/promises";
|
|
108313
|
-
import { extname, resolve as resolve19, sep as sep4 } from "node:path";
|
|
108461
|
+
import { extname as extname2, resolve as resolve19, sep as sep4 } from "node:path";
|
|
108314
108462
|
import { randomUUID } from "node:crypto";
|
|
108315
108463
|
function getImagesDir(rootPath) {
|
|
108316
108464
|
return resolve19(rootPath, ".vibeman/assets/images");
|
|
@@ -108322,7 +108470,7 @@ async function writeImageAsset(options2) {
|
|
|
108322
108470
|
const imagesDir = getImagesDir(options2.rootPath);
|
|
108323
108471
|
await mkdir4(imagesDir, { recursive: true });
|
|
108324
108472
|
const extFromMime = imageMimeToExt[options2.mimeType] ?? null;
|
|
108325
|
-
const extFromNameRaw = options2.originalName ? sanitizeExt(
|
|
108473
|
+
const extFromNameRaw = options2.originalName ? sanitizeExt(extname2(options2.originalName)) : null;
|
|
108326
108474
|
const extFromName = extFromNameRaw ? imageExtAliases[extFromNameRaw] ?? null : null;
|
|
108327
108475
|
const ext = extFromMime ?? extFromName ?? null;
|
|
108328
108476
|
if (!ext) {
|
|
@@ -108647,12 +108795,12 @@ var init_model_catalog = __esm(() => {
|
|
|
108647
108795
|
});
|
|
108648
108796
|
|
|
108649
108797
|
// ../api/src/server/routes/cli-settings.ts
|
|
108650
|
-
import { delimiter as delimiter4, dirname as
|
|
108798
|
+
import { delimiter as delimiter4, dirname as dirname6 } from "node:path";
|
|
108651
108799
|
function withExecutableOnPath(env, executable) {
|
|
108652
108800
|
if (!executable) {
|
|
108653
108801
|
return env;
|
|
108654
108802
|
}
|
|
108655
|
-
const dir =
|
|
108803
|
+
const dir = dirname6(executable);
|
|
108656
108804
|
const basePath = env.PATH ?? process.env.PATH ?? "";
|
|
108657
108805
|
const combined = [dir, basePath].filter(Boolean).join(delimiter4);
|
|
108658
108806
|
return { ...env, PATH: combined };
|
|
@@ -112852,7 +113000,7 @@ var init_github = __esm(() => {
|
|
|
112852
113000
|
});
|
|
112853
113001
|
|
|
112854
113002
|
// ../api/src/services/integrations/github-sync.ts
|
|
112855
|
-
import { join as
|
|
113003
|
+
import { join as join7, resolve as resolve20 } from "node:path";
|
|
112856
113004
|
import { mkdir as mkdir5, writeFile as writeFile6 } from "node:fs/promises";
|
|
112857
113005
|
function mapIssueStateToTaskStatus(state2) {
|
|
112858
113006
|
return state2 === "open" ? "backlog" : "done";
|
|
@@ -112873,7 +113021,7 @@ async function findTaskForIssue(rootPath, owner, repo, issueNumber) {
|
|
|
112873
113021
|
continue;
|
|
112874
113022
|
}
|
|
112875
113023
|
try {
|
|
112876
|
-
const content = await readFileContent(rootPath,
|
|
113024
|
+
const content = await readFileContent(rootPath, join7(tasksPath, file2.name));
|
|
112877
113025
|
const parsed = import_gray_matter3.default(content);
|
|
112878
113026
|
if (isTaskLinkedToIssue(parsed.data, owner, repo, issueNumber)) {
|
|
112879
113027
|
return {
|
|
@@ -112923,7 +113071,7 @@ async function syncIssueToTask(rootPath, owner, repo, issue2, options2) {
|
|
|
112923
113071
|
};
|
|
112924
113072
|
const content = import_gray_matter3.default.stringify(taskBody, updatedFrontmatter, frontmatterYamlOptions2);
|
|
112925
113073
|
const tasksDir = resolve20(rootPath, ".vibeman/tasks");
|
|
112926
|
-
await writeFile6(
|
|
113074
|
+
await writeFile6(join7(tasksDir, existingTask.filename), content);
|
|
112927
113075
|
return { action: "updated", filename: existingTask.filename };
|
|
112928
113076
|
} else {
|
|
112929
113077
|
const taskId = generateTaskIdFromIssue(issue2);
|
|
@@ -112943,7 +113091,7 @@ async function syncIssueToTask(rootPath, owner, repo, issue2, options2) {
|
|
|
112943
113091
|
const content = import_gray_matter3.default.stringify(taskBody, frontmatter, frontmatterYamlOptions2);
|
|
112944
113092
|
const tasksDir = resolve20(rootPath, ".vibeman/tasks");
|
|
112945
113093
|
await mkdir5(tasksDir, { recursive: true });
|
|
112946
|
-
await writeFile6(
|
|
113094
|
+
await writeFile6(join7(tasksDir, filename), content);
|
|
112947
113095
|
return { action: "created", filename };
|
|
112948
113096
|
}
|
|
112949
113097
|
}
|
|
@@ -113008,7 +113156,7 @@ async function syncTaskToGitHub(db, rootPath, taskFilename) {
|
|
|
113008
113156
|
throw new Error("GitHub integration is not configured");
|
|
113009
113157
|
}
|
|
113010
113158
|
const tasksPath = ".vibeman/tasks";
|
|
113011
|
-
const content = await readFileContent(rootPath,
|
|
113159
|
+
const content = await readFileContent(rootPath, join7(tasksPath, taskFilename));
|
|
113012
113160
|
const parsed = import_gray_matter3.default(content);
|
|
113013
113161
|
const githubRepo = parsed.data.github_repo;
|
|
113014
113162
|
const githubIssueNumberRaw = parsed.data.github_issue_number;
|
|
@@ -113037,7 +113185,7 @@ async function syncTaskToGitHub(db, rootPath, taskFilename) {
|
|
|
113037
113185
|
};
|
|
113038
113186
|
const updatedContent = import_gray_matter3.default.stringify(parsed.content, updatedFrontmatter, stringifyOptions);
|
|
113039
113187
|
const tasksDir = resolve20(rootPath, ".vibeman/tasks");
|
|
113040
|
-
await writeFile6(
|
|
113188
|
+
await writeFile6(join7(tasksDir, taskFilename), updatedContent);
|
|
113041
113189
|
}
|
|
113042
113190
|
async function syncIssueToTaskFromGitHub(db, rootPath, taskFilename) {
|
|
113043
113191
|
const config2 = await getGitHubConfig(db);
|
|
@@ -113045,7 +113193,7 @@ async function syncIssueToTaskFromGitHub(db, rootPath, taskFilename) {
|
|
|
113045
113193
|
throw new Error("GitHub integration is not configured");
|
|
113046
113194
|
}
|
|
113047
113195
|
const tasksPath = ".vibeman/tasks";
|
|
113048
|
-
const content = await readFileContent(rootPath,
|
|
113196
|
+
const content = await readFileContent(rootPath, join7(tasksPath, taskFilename));
|
|
113049
113197
|
const parsed = import_gray_matter3.default(content);
|
|
113050
113198
|
const githubRepo = parsed.data.github_repo;
|
|
113051
113199
|
const githubIssueNumberRaw = parsed.data.github_issue_number;
|
|
@@ -113065,7 +113213,7 @@ async function syncIssueToTaskFromGitHub(db, rootPath, taskFilename) {
|
|
|
113065
113213
|
}
|
|
113066
113214
|
async function linkTaskToGitHubIssue(rootPath, taskFilename, owner, repo, issueNumber, issueUrl) {
|
|
113067
113215
|
const tasksPath = ".vibeman/tasks";
|
|
113068
|
-
const content = await readFileContent(rootPath,
|
|
113216
|
+
const content = await readFileContent(rootPath, join7(tasksPath, taskFilename));
|
|
113069
113217
|
const parsed = import_gray_matter3.default(content);
|
|
113070
113218
|
const repoIdentifier = `${owner}/${repo}`;
|
|
113071
113219
|
const githubMetadata = {
|
|
@@ -113081,11 +113229,11 @@ async function linkTaskToGitHubIssue(rootPath, taskFilename, owner, repo, issueN
|
|
|
113081
113229
|
};
|
|
113082
113230
|
const updatedContent = import_gray_matter3.default.stringify(parsed.content, updatedFrontmatter, stringifyOptions);
|
|
113083
113231
|
const tasksDir = resolve20(rootPath, ".vibeman/tasks");
|
|
113084
|
-
await writeFile6(
|
|
113232
|
+
await writeFile6(join7(tasksDir, taskFilename), updatedContent);
|
|
113085
113233
|
}
|
|
113086
113234
|
async function unlinkTaskFromGitHubIssue(rootPath, taskFilename) {
|
|
113087
113235
|
const tasksPath = ".vibeman/tasks";
|
|
113088
|
-
const content = await readFileContent(rootPath,
|
|
113236
|
+
const content = await readFileContent(rootPath, join7(tasksPath, taskFilename));
|
|
113089
113237
|
const parsed = import_gray_matter3.default(content);
|
|
113090
113238
|
const updatedFrontmatter = { ...parsed.data };
|
|
113091
113239
|
delete updatedFrontmatter.github_repo;
|
|
@@ -113095,7 +113243,7 @@ async function unlinkTaskFromGitHubIssue(rootPath, taskFilename) {
|
|
|
113095
113243
|
updatedFrontmatter.updated_at = new Date().toISOString();
|
|
113096
113244
|
const updatedContent = import_gray_matter3.default.stringify(parsed.content, updatedFrontmatter, stringifyOptions);
|
|
113097
113245
|
const tasksDir = resolve20(rootPath, ".vibeman/tasks");
|
|
113098
|
-
await writeFile6(
|
|
113246
|
+
await writeFile6(join7(tasksDir, taskFilename), updatedContent);
|
|
113099
113247
|
}
|
|
113100
113248
|
var import_gray_matter3, stringifyOptions, parseTimestamp = (value) => {
|
|
113101
113249
|
if (typeof value !== "string")
|
|
@@ -113127,7 +113275,7 @@ var import_gray_matter3, stringifyOptions, parseTimestamp = (value) => {
|
|
|
113127
113275
|
continue;
|
|
113128
113276
|
}
|
|
113129
113277
|
try {
|
|
113130
|
-
const content = await readFileContent(rootPath,
|
|
113278
|
+
const content = await readFileContent(rootPath, join7(tasksPath, file2.name));
|
|
113131
113279
|
const parsed = import_gray_matter3.default(content);
|
|
113132
113280
|
if (!shouldPushTaskToGitHub(parsed.data, owner, repo))
|
|
113133
113281
|
continue;
|
|
@@ -113358,9 +113506,283 @@ var init_github3 = __esm(() => {
|
|
|
113358
113506
|
});
|
|
113359
113507
|
});
|
|
113360
113508
|
|
|
113509
|
+
// ../api/src/services/feedback.ts
|
|
113510
|
+
function shouldRedactUnixPath(path3) {
|
|
113511
|
+
if (path3 === "~")
|
|
113512
|
+
return false;
|
|
113513
|
+
return path3.startsWith("~/") || path3.startsWith("/");
|
|
113514
|
+
}
|
|
113515
|
+
function isSensitiveEnvKey(key) {
|
|
113516
|
+
return /(token|secret|password|passwd|auth|session|cookie|api_?key)/i.test(key);
|
|
113517
|
+
}
|
|
113518
|
+
function sanitizeText(value) {
|
|
113519
|
+
return value.replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, "[REDACTED_EMAIL]").replace(/\b(Bearer\s+)[A-Za-z0-9._\-]+/gi, "$1[REDACTED_TOKEN]").replace(/\b(sk-[A-Za-z0-9]{12,})\b/g, "[REDACTED_TOKEN]").replace(/\b(gh[pousr]_[A-Za-z0-9]{12,})\b/g, "[REDACTED_TOKEN]").replace(/\b(github_pat_[A-Za-z0-9_]{20,})\b/g, "[REDACTED_TOKEN]").replace(/\b(xox[baprs]-[A-Za-z0-9-]{10,})\b/g, "[REDACTED_TOKEN]").replace(ABSOLUTE_WINDOWS_PATH_PATTERN, (_, prefix, path3) => {
|
|
113520
|
+
return `${prefix}[REDACTED_PATH]`;
|
|
113521
|
+
}).replace(ABSOLUTE_UNIX_PATH_PATTERN, (_, prefix, path3) => {
|
|
113522
|
+
return shouldRedactUnixPath(path3) ? `${prefix}[REDACTED_PATH]` : `${prefix}${path3}`;
|
|
113523
|
+
}).replace(ENV_ASSIGNMENT_PATTERN, (match, key) => {
|
|
113524
|
+
return isSensitiveEnvKey(key) ? `${key}=[REDACTED_TOKEN]` : match;
|
|
113525
|
+
});
|
|
113526
|
+
}
|
|
113527
|
+
function collapseBlankLines(value) {
|
|
113528
|
+
return value.replace(/\n{3,}/g, `
|
|
113529
|
+
|
|
113530
|
+
`).trim();
|
|
113531
|
+
}
|
|
113532
|
+
function sanitizeFeedbackText(value) {
|
|
113533
|
+
return collapseBlankLines(sanitizeText(value.trim()));
|
|
113534
|
+
}
|
|
113535
|
+
function sanitizeBrowserFeedbackContext(input) {
|
|
113536
|
+
if (!input)
|
|
113537
|
+
return;
|
|
113538
|
+
const entries = Object.entries(input).flatMap(([key, value]) => {
|
|
113539
|
+
if (typeof value !== "string")
|
|
113540
|
+
return [];
|
|
113541
|
+
const sanitized = sanitizeFeedbackText(value);
|
|
113542
|
+
return sanitized ? [[key, sanitized]] : [];
|
|
113543
|
+
});
|
|
113544
|
+
return entries.length > 0 ? Object.fromEntries(entries) : undefined;
|
|
113545
|
+
}
|
|
113546
|
+
function fallbackTitleFromBody(body) {
|
|
113547
|
+
const line = body.split(`
|
|
113548
|
+
`).map((entry) => entry.trim()).find((entry) => entry.length > 0 && !entry.startsWith("#") && !entry.startsWith("- "));
|
|
113549
|
+
if (!line)
|
|
113550
|
+
return "Feedback";
|
|
113551
|
+
return line.slice(0, FEEDBACK_TITLE_MAX_LENGTH);
|
|
113552
|
+
}
|
|
113553
|
+
function normalizeFeedbackIssueDraft(input) {
|
|
113554
|
+
const title = sanitizeFeedbackText(input.title ?? "").replace(/\s+/g, " ").trim();
|
|
113555
|
+
const body = sanitizeFeedbackText(input.body ?? "");
|
|
113556
|
+
return {
|
|
113557
|
+
title: (title || fallbackTitleFromBody(body) || "Feedback").slice(0, FEEDBACK_TITLE_MAX_LENGTH),
|
|
113558
|
+
body: body.slice(0, FEEDBACK_BODY_MAX_LENGTH) || "No additional details provided."
|
|
113559
|
+
};
|
|
113560
|
+
}
|
|
113561
|
+
function sanitizeFeedbackIssueDraft(input) {
|
|
113562
|
+
return normalizeFeedbackIssueDraft(input);
|
|
113563
|
+
}
|
|
113564
|
+
function parsePolishedFeedbackOutput(output) {
|
|
113565
|
+
const trimmed2 = output.trim();
|
|
113566
|
+
if (!trimmed2)
|
|
113567
|
+
return null;
|
|
113568
|
+
const fencedJsonMatch = trimmed2.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
113569
|
+
const jsonCandidate = fencedJsonMatch?.[1] ?? trimmed2;
|
|
113570
|
+
const jsonMatch = jsonCandidate.match(/\{[\s\S]*\}/);
|
|
113571
|
+
if (jsonMatch) {
|
|
113572
|
+
try {
|
|
113573
|
+
return feedbackIssueDraftSchema.parse(JSON.parse(jsonMatch[0]));
|
|
113574
|
+
} catch {}
|
|
113575
|
+
}
|
|
113576
|
+
const titleMatch = trimmed2.match(/(?:^|\n)TITLE:\s*(.+?)(?:\n|$)/i);
|
|
113577
|
+
const bodyMatch = trimmed2.match(/(?:^|\n)BODY:\s*([\s\S]+)/i);
|
|
113578
|
+
if (titleMatch && bodyMatch) {
|
|
113579
|
+
return normalizeFeedbackIssueDraft({
|
|
113580
|
+
title: titleMatch[1],
|
|
113581
|
+
body: bodyMatch[1]
|
|
113582
|
+
});
|
|
113583
|
+
}
|
|
113584
|
+
return null;
|
|
113585
|
+
}
|
|
113586
|
+
function buildBrowserContextSection(browserContext) {
|
|
113587
|
+
const entries = [
|
|
113588
|
+
browserContext?.platform ? `- Platform: ${browserContext.platform}` : null,
|
|
113589
|
+
browserContext?.operatingSystem ? `- OS: ${browserContext.operatingSystem}` : null,
|
|
113590
|
+
browserContext?.browser ? `- Browser: ${browserContext.browser}` : null,
|
|
113591
|
+
browserContext?.viewport ? `- Viewport: ${browserContext.viewport}` : null,
|
|
113592
|
+
browserContext?.devicePixelRatio ? `- Device Pixel Ratio: ${browserContext.devicePixelRatio}` : null,
|
|
113593
|
+
browserContext?.language ? `- Language: ${browserContext.language}` : null,
|
|
113594
|
+
browserContext?.touchSupport ? `- Touch Support: ${browserContext.touchSupport}` : null,
|
|
113595
|
+
browserContext?.walletContext ? `- Wallet/Web3 Context: ${browserContext.walletContext}` : null,
|
|
113596
|
+
browserContext?.appVersion ? `- App Version: ${browserContext.appVersion}` : null
|
|
113597
|
+
].filter(Boolean);
|
|
113598
|
+
if (entries.length === 0)
|
|
113599
|
+
return "Not provided.";
|
|
113600
|
+
return ["Browser context captured from the web app:", ...entries].join(`
|
|
113601
|
+
`);
|
|
113602
|
+
}
|
|
113603
|
+
function buildReproductionContextTemplate() {
|
|
113604
|
+
return [
|
|
113605
|
+
"- Platform: Not provided.",
|
|
113606
|
+
"- OS: Not provided.",
|
|
113607
|
+
"- Browser: Not provided.",
|
|
113608
|
+
"- Viewport: Not provided.",
|
|
113609
|
+
"- Wallet/Web3 Context: Not provided.",
|
|
113610
|
+
"- App Version: Not provided."
|
|
113611
|
+
].join(`
|
|
113612
|
+
`);
|
|
113613
|
+
}
|
|
113614
|
+
function buildFeedbackPolishPrompt(input, browserContext) {
|
|
113615
|
+
return [
|
|
113616
|
+
"Rewrite this user feedback into a GitHub issue draft.",
|
|
113617
|
+
"Return ONLY valid JSON with this shape:",
|
|
113618
|
+
'{"title":"string","body":"string"}',
|
|
113619
|
+
"",
|
|
113620
|
+
"Rules:",
|
|
113621
|
+
"- Keep the result deterministic and concise.",
|
|
113622
|
+
"- Do not include private information, secrets, local paths, or email addresses.",
|
|
113623
|
+
"- Use this exact markdown template for body sections and preserve the headings/order:",
|
|
113624
|
+
"## Summary",
|
|
113625
|
+
"## Problem",
|
|
113626
|
+
"## Reproduction Context",
|
|
113627
|
+
"## Desired Outcome",
|
|
113628
|
+
'- Use bullet points under "## Reproduction Context", with one context field per line prefixed by "-".',
|
|
113629
|
+
"- Prefer these reproduction context fields when relevant: Platform, OS, Browser, Viewport, Wallet/Web3 Context, App Version.",
|
|
113630
|
+
"- Use the browser context below when it helps reproducibility, but keep it compact and non-sensitive.",
|
|
113631
|
+
'- If a section has no useful details, write "Not provided."',
|
|
113632
|
+
"",
|
|
113633
|
+
`Current title: ${input.title}`,
|
|
113634
|
+
"Current details:",
|
|
113635
|
+
input.body,
|
|
113636
|
+
"",
|
|
113637
|
+
"Available reproduction context:",
|
|
113638
|
+
buildBrowserContextSection(browserContext)
|
|
113639
|
+
].join(`
|
|
113640
|
+
`);
|
|
113641
|
+
}
|
|
113642
|
+
function buildFeedbackDraftFromInput(input) {
|
|
113643
|
+
const normalized = normalizeFeedbackIssueDraft({
|
|
113644
|
+
title: input.title,
|
|
113645
|
+
body: input.body
|
|
113646
|
+
});
|
|
113647
|
+
return {
|
|
113648
|
+
title: normalized.title,
|
|
113649
|
+
body: [
|
|
113650
|
+
"## Summary",
|
|
113651
|
+
normalized.title,
|
|
113652
|
+
"",
|
|
113653
|
+
"## Problem",
|
|
113654
|
+
normalized.body || "Not provided.",
|
|
113655
|
+
"",
|
|
113656
|
+
"## Reproduction Context",
|
|
113657
|
+
buildReproductionContextTemplate(),
|
|
113658
|
+
"",
|
|
113659
|
+
"## Desired Outcome",
|
|
113660
|
+
"Not provided."
|
|
113661
|
+
].join(`
|
|
113662
|
+
`)
|
|
113663
|
+
};
|
|
113664
|
+
}
|
|
113665
|
+
function buildGitHubIssueCreateUrl(input) {
|
|
113666
|
+
const params = new URLSearchParams({
|
|
113667
|
+
title: input.draft.title,
|
|
113668
|
+
body: input.draft.body,
|
|
113669
|
+
labels: "feedback"
|
|
113670
|
+
});
|
|
113671
|
+
return `https://github.com/${input.owner}/${input.repo}/issues/new?${params.toString()}`;
|
|
113672
|
+
}
|
|
113673
|
+
var FEEDBACK_SANITIZED_FIELDS, feedbackIssueDraftSchema, FEEDBACK_TITLE_MAX_LENGTH = 120, FEEDBACK_BODY_MAX_LENGTH = 8000, ENV_ASSIGNMENT_PATTERN, ABSOLUTE_UNIX_PATH_PATTERN, ABSOLUTE_WINDOWS_PATH_PATTERN;
|
|
113674
|
+
var init_feedback = __esm(() => {
|
|
113675
|
+
init_zod();
|
|
113676
|
+
FEEDBACK_SANITIZED_FIELDS = [
|
|
113677
|
+
"Email addresses",
|
|
113678
|
+
"Bearer/API/GitHub-style tokens",
|
|
113679
|
+
"Absolute local filesystem paths",
|
|
113680
|
+
"Sensitive env assignments such as TOKEN=..."
|
|
113681
|
+
];
|
|
113682
|
+
feedbackIssueDraftSchema = exports_external.object({
|
|
113683
|
+
title: exports_external.string().trim().min(1),
|
|
113684
|
+
body: exports_external.string().trim().min(1)
|
|
113685
|
+
});
|
|
113686
|
+
ENV_ASSIGNMENT_PATTERN = /\b([A-Za-z_][A-Za-z0-9_]*)=([^\s]+)/g;
|
|
113687
|
+
ABSOLUTE_UNIX_PATH_PATTERN = /(^|[\s([{'"`])((?:~|\/)[^\s)\]}'"`]+)(?=$|[\s)\]},'"`.!?;:])/gm;
|
|
113688
|
+
ABSOLUTE_WINDOWS_PATH_PATTERN = /(^|[\s([{'"`])([A-Za-z]:\\[^\s)\]}'"`]+)(?=$|[\s)\]},'"`.!?;:])/gm;
|
|
113689
|
+
});
|
|
113690
|
+
|
|
113691
|
+
// ../api/src/server/routes/feedback.ts
|
|
113692
|
+
function getFeedbackPolishFailureMessage(result) {
|
|
113693
|
+
if (result.aborted)
|
|
113694
|
+
return FEEDBACK_POLISH_TIMEOUT_MESSAGE;
|
|
113695
|
+
return result.error ?? "Failed to polish feedback draft.";
|
|
113696
|
+
}
|
|
113697
|
+
var feedbackDraftSchema, browserFeedbackContextSchema, feedbackPolishInputSchema, FEEDBACK_POLISH_TIMEOUT_MS = 30000, FEEDBACK_POLISH_TIMEOUT_MESSAGE = "Polish timed out after 30 seconds. Try again with a shorter draft or verify the default coding agent is available.", FEEDBACK_REPOSITORY, feedbackRouter;
|
|
113698
|
+
var init_feedback2 = __esm(() => {
|
|
113699
|
+
init_dist4();
|
|
113700
|
+
init_zod();
|
|
113701
|
+
init_trpc();
|
|
113702
|
+
init_agents();
|
|
113703
|
+
init_feedback();
|
|
113704
|
+
feedbackDraftSchema = exports_external.object({
|
|
113705
|
+
title: exports_external.string().trim().max(200).optional(),
|
|
113706
|
+
body: exports_external.string().trim().max(12000)
|
|
113707
|
+
});
|
|
113708
|
+
browserFeedbackContextSchema = exports_external.object({
|
|
113709
|
+
platform: exports_external.string().trim().max(40).optional(),
|
|
113710
|
+
operatingSystem: exports_external.string().trim().max(80).optional(),
|
|
113711
|
+
browser: exports_external.string().trim().max(80).optional(),
|
|
113712
|
+
viewport: exports_external.string().trim().max(40).optional(),
|
|
113713
|
+
devicePixelRatio: exports_external.string().trim().max(20).optional(),
|
|
113714
|
+
language: exports_external.string().trim().max(40).optional(),
|
|
113715
|
+
touchSupport: exports_external.string().trim().max(20).optional(),
|
|
113716
|
+
walletContext: exports_external.string().trim().max(240).optional(),
|
|
113717
|
+
appVersion: exports_external.string().trim().max(80).optional()
|
|
113718
|
+
});
|
|
113719
|
+
feedbackPolishInputSchema = feedbackDraftSchema.extend({
|
|
113720
|
+
browserContext: browserFeedbackContextSchema.optional()
|
|
113721
|
+
});
|
|
113722
|
+
FEEDBACK_REPOSITORY = {
|
|
113723
|
+
owner: "brucexu-eth",
|
|
113724
|
+
repo: "vibeman"
|
|
113725
|
+
};
|
|
113726
|
+
feedbackRouter = t.router({
|
|
113727
|
+
polishDraft: dbProcedure.input(feedbackPolishInputSchema).mutation(async ({ ctx, input }) => {
|
|
113728
|
+
const sanitizedInput = normalizeFeedbackIssueDraft(input);
|
|
113729
|
+
const browserContext = sanitizeBrowserFeedbackContext(input.browserContext);
|
|
113730
|
+
const fallbackDraft = buildFeedbackDraftFromInput(sanitizedInput);
|
|
113731
|
+
const timeoutController = new AbortController;
|
|
113732
|
+
const timeoutId = setTimeout(() => {
|
|
113733
|
+
timeoutController.abort();
|
|
113734
|
+
}, FEEDBACK_POLISH_TIMEOUT_MS);
|
|
113735
|
+
const result = await executeAgentExecutionRequest(ctx.db, {
|
|
113736
|
+
source: "task",
|
|
113737
|
+
runId: `feedback-polish-${Date.now()}`,
|
|
113738
|
+
nodeKey: "feedback-polish",
|
|
113739
|
+
root: ctx.root,
|
|
113740
|
+
prompt: buildFeedbackPolishPrompt(sanitizedInput, browserContext),
|
|
113741
|
+
resumeThread: false,
|
|
113742
|
+
executorConfig: {
|
|
113743
|
+
permissionMode: "read-only"
|
|
113744
|
+
},
|
|
113745
|
+
signal: timeoutController.signal,
|
|
113746
|
+
logContext: { module: "feedback" }
|
|
113747
|
+
}).finally(() => {
|
|
113748
|
+
clearTimeout(timeoutId);
|
|
113749
|
+
});
|
|
113750
|
+
if (!result.success) {
|
|
113751
|
+
throw new TRPCError({
|
|
113752
|
+
code: "INTERNAL_SERVER_ERROR",
|
|
113753
|
+
message: getFeedbackPolishFailureMessage(result)
|
|
113754
|
+
});
|
|
113755
|
+
}
|
|
113756
|
+
const polished = parsePolishedFeedbackOutput(result.output ?? "");
|
|
113757
|
+
const draft = sanitizeFeedbackIssueDraft(polished ?? fallbackDraft);
|
|
113758
|
+
return createResponse(ctx, {
|
|
113759
|
+
draft,
|
|
113760
|
+
provider: result.provider,
|
|
113761
|
+
model: result.model,
|
|
113762
|
+
sanitizedFields: FEEDBACK_SANITIZED_FIELDS
|
|
113763
|
+
});
|
|
113764
|
+
}),
|
|
113765
|
+
prepareSubmission: dbProcedure.input(feedbackDraftSchema).mutation(async ({ ctx, input }) => {
|
|
113766
|
+
const draft = sanitizeFeedbackIssueDraft(input);
|
|
113767
|
+
const url2 = buildGitHubIssueCreateUrl({
|
|
113768
|
+
owner: FEEDBACK_REPOSITORY.owner,
|
|
113769
|
+
repo: FEEDBACK_REPOSITORY.repo,
|
|
113770
|
+
draft
|
|
113771
|
+
});
|
|
113772
|
+
return createResponse(ctx, {
|
|
113773
|
+
draft,
|
|
113774
|
+
url: url2,
|
|
113775
|
+
owner: FEEDBACK_REPOSITORY.owner,
|
|
113776
|
+
repo: FEEDBACK_REPOSITORY.repo,
|
|
113777
|
+
sanitizedFields: FEEDBACK_SANITIZED_FIELDS
|
|
113778
|
+
});
|
|
113779
|
+
})
|
|
113780
|
+
});
|
|
113781
|
+
});
|
|
113782
|
+
|
|
113361
113783
|
// ../api/src/server/routes/onboarding.ts
|
|
113362
|
-
import { readFile as
|
|
113363
|
-
import { basename as basename2, join as
|
|
113784
|
+
import { readFile as readFile7, readdir as readdir4, rename as rename2, rm as rm3, mkdir as mkdir6, writeFile as writeFile7 } from "node:fs/promises";
|
|
113785
|
+
import { basename as basename2, join as join8, resolve as resolve21 } from "node:path";
|
|
113364
113786
|
import { spawn as spawn8 } from "node:child_process";
|
|
113365
113787
|
function buildInitialOnboardingState(nowIso) {
|
|
113366
113788
|
return {
|
|
@@ -113413,10 +113835,10 @@ ${err instanceof Error ? err.message : String(err)}`,
|
|
|
113413
113835
|
});
|
|
113414
113836
|
}
|
|
113415
113837
|
async function moveDirectoryContents(srcDir, destDir) {
|
|
113416
|
-
const entries = await
|
|
113838
|
+
const entries = await readdir4(srcDir);
|
|
113417
113839
|
const moved = [];
|
|
113418
113840
|
for (const entry of entries) {
|
|
113419
|
-
await rename2(
|
|
113841
|
+
await rename2(join8(srcDir, entry), join8(destDir, entry));
|
|
113420
113842
|
moved.push(entry);
|
|
113421
113843
|
}
|
|
113422
113844
|
return moved;
|
|
@@ -113491,7 +113913,7 @@ function buildTemplateWorkspace(root) {
|
|
|
113491
113913
|
async function patchGeneratedPackageName(root, desiredName) {
|
|
113492
113914
|
const packageJsonPath = resolve21(root, "package.json");
|
|
113493
113915
|
try {
|
|
113494
|
-
const raw2 = await
|
|
113916
|
+
const raw2 = await readFile7(packageJsonPath, "utf8");
|
|
113495
113917
|
const pkg = JSON.parse(raw2);
|
|
113496
113918
|
const currentName = typeof pkg.name === "string" ? pkg.name.trim() : "";
|
|
113497
113919
|
if (currentName.length === 0 || currentName.includes("vibeman-init-tmp")) {
|
|
@@ -113510,7 +113932,7 @@ async function patchGeneratedT3ImportAlias(root, desiredAlias) {
|
|
|
113510
113932
|
}
|
|
113511
113933
|
const tsconfigPath = resolve21(root, "tsconfig.json");
|
|
113512
113934
|
try {
|
|
113513
|
-
const raw2 = await
|
|
113935
|
+
const raw2 = await readFile7(tsconfigPath, "utf8");
|
|
113514
113936
|
const config2 = JSON.parse(raw2);
|
|
113515
113937
|
const paths = config2.compilerOptions?.paths;
|
|
113516
113938
|
const current = paths?.["~/*"];
|
|
@@ -113712,7 +114134,7 @@ var init_onboarding = __esm(() => {
|
|
|
113712
114134
|
let packageName = null;
|
|
113713
114135
|
let packageDescription = null;
|
|
113714
114136
|
try {
|
|
113715
|
-
const raw2 = await
|
|
114137
|
+
const raw2 = await readFile7(resolve21(ctx.root, "package.json"), "utf8");
|
|
113716
114138
|
const pkg = JSON.parse(raw2);
|
|
113717
114139
|
if (typeof pkg.name === "string" && pkg.name.trim()) {
|
|
113718
114140
|
packageName = pkg.name.trim();
|
|
@@ -113729,7 +114151,7 @@ var init_onboarding = __esm(() => {
|
|
|
113729
114151
|
let hasPackageJson = false;
|
|
113730
114152
|
let detectedFramework = null;
|
|
113731
114153
|
try {
|
|
113732
|
-
const entries = await
|
|
114154
|
+
const entries = await readdir4(ctx.root, { withFileTypes: true });
|
|
113733
114155
|
for (const entry of entries) {
|
|
113734
114156
|
if (IGNORED.has(entry.name))
|
|
113735
114157
|
continue;
|
|
@@ -113742,7 +114164,7 @@ var init_onboarding = __esm(() => {
|
|
|
113742
114164
|
} catch {}
|
|
113743
114165
|
if (hasPackageJson) {
|
|
113744
114166
|
try {
|
|
113745
|
-
const raw2 = await
|
|
114167
|
+
const raw2 = await readFile7(resolve21(ctx.root, "package.json"), "utf8");
|
|
113746
114168
|
const pkg = JSON.parse(raw2);
|
|
113747
114169
|
const all = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
113748
114170
|
if (all["next"] && all["@trpc/server"])
|
|
@@ -113782,13 +114204,13 @@ var init_onboarding = __esm(() => {
|
|
|
113782
114204
|
const scaffoldPath = shouldRunInTmpDir ? resolve21(tmpPath, workspace.projectDirName) : resolve21(ctx.root, workspace.scaffoldDir);
|
|
113783
114205
|
const command = buildTemplateInitCommand(input, commandTargetDir);
|
|
113784
114206
|
try {
|
|
113785
|
-
await
|
|
114207
|
+
await rm3(tmpPath, { recursive: true, force: true });
|
|
113786
114208
|
} catch {}
|
|
113787
114209
|
await mkdir6(tmpPath, { recursive: true });
|
|
113788
114210
|
const result = await runShellCommand(command, commandCwd);
|
|
113789
114211
|
if (!result.success) {
|
|
113790
114212
|
try {
|
|
113791
|
-
await
|
|
114213
|
+
await rm3(tmpPath, { recursive: true, force: true });
|
|
113792
114214
|
} catch {}
|
|
113793
114215
|
const detail = (result.stderr || result.stdout).trim().slice(-2000);
|
|
113794
114216
|
throw new TRPCError({
|
|
@@ -113819,7 +114241,7 @@ ${detail}`
|
|
|
113819
114241
|
throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: msg });
|
|
113820
114242
|
} finally {
|
|
113821
114243
|
try {
|
|
113822
|
-
await
|
|
114244
|
+
await rm3(tmpPath, { recursive: true, force: true });
|
|
113823
114245
|
} catch {}
|
|
113824
114246
|
}
|
|
113825
114247
|
return createResponse(ctx, {
|
|
@@ -113990,7 +114412,7 @@ Rules:
|
|
|
113990
114412
|
};
|
|
113991
114413
|
const body = task2.body.trim() || task2.title;
|
|
113992
114414
|
const content = stringifyTaskMarkdown(body, frontmatter);
|
|
113993
|
-
await writeFile7(
|
|
114415
|
+
await writeFile7(join8(tasksDir, filename), content);
|
|
113994
114416
|
created.push(filename);
|
|
113995
114417
|
}
|
|
113996
114418
|
return createResponse(ctx, { created });
|
|
@@ -114013,6 +114435,7 @@ var init_router2 = __esm(() => {
|
|
|
114013
114435
|
init_settings2();
|
|
114014
114436
|
init_cli_settings();
|
|
114015
114437
|
init_github3();
|
|
114438
|
+
init_feedback2();
|
|
114016
114439
|
init_onboarding();
|
|
114017
114440
|
init_trpc();
|
|
114018
114441
|
appRouter = t.router({
|
|
@@ -114028,6 +114451,7 @@ var init_router2 = __esm(() => {
|
|
|
114028
114451
|
settings: settingsRouter,
|
|
114029
114452
|
cliSettings: cliSettingsRouter,
|
|
114030
114453
|
github: githubRouter,
|
|
114454
|
+
feedback: feedbackRouter,
|
|
114031
114455
|
onboarding: onboardingRouter
|
|
114032
114456
|
});
|
|
114033
114457
|
});
|
|
@@ -122216,7 +122640,7 @@ var require_mime_types = __commonJS((exports) => {
|
|
|
122216
122640
|
* MIT Licensed
|
|
122217
122641
|
*/
|
|
122218
122642
|
var db = require_mime_db();
|
|
122219
|
-
var
|
|
122643
|
+
var extname3 = __require("path").extname;
|
|
122220
122644
|
var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/;
|
|
122221
122645
|
var TEXT_TYPE_REGEXP = /^text\//i;
|
|
122222
122646
|
exports.charset = charset;
|
|
@@ -122271,7 +122695,7 @@ var require_mime_types = __commonJS((exports) => {
|
|
|
122271
122695
|
if (!path3 || typeof path3 !== "string") {
|
|
122272
122696
|
return false;
|
|
122273
122697
|
}
|
|
122274
|
-
var extension2 =
|
|
122698
|
+
var extension2 = extname3("x." + path3).toLowerCase().substr(1);
|
|
122275
122699
|
if (!extension2) {
|
|
122276
122700
|
return false;
|
|
122277
122701
|
}
|
|
@@ -122735,10 +123159,10 @@ var require_error = __commonJS((exports, module) => {
|
|
|
122735
123159
|
|
|
122736
123160
|
// ../../node_modules/serve-handler/src/index.js
|
|
122737
123161
|
var require_src3 = __commonJS((exports, module) => {
|
|
122738
|
-
var { promisify:
|
|
123162
|
+
var { promisify: promisify3 } = __require("util");
|
|
122739
123163
|
var path3 = __require("path");
|
|
122740
123164
|
var { createHash: createHash2 } = __require("crypto");
|
|
122741
|
-
var { realpath, lstat:
|
|
123165
|
+
var { realpath, lstat: lstat3, createReadStream, readdir: readdir5 } = __require("fs");
|
|
122742
123166
|
var url2 = __require("url");
|
|
122743
123167
|
var slasher = require_glob_slash();
|
|
122744
123168
|
var minimatch = require_minimatch();
|
|
@@ -123126,10 +123550,10 @@ var require_src3 = __commonJS((exports, module) => {
|
|
|
123126
123550
|
return sendError(...args);
|
|
123127
123551
|
};
|
|
123128
123552
|
var getHandlers = (methods) => Object.assign({
|
|
123129
|
-
lstat:
|
|
123130
|
-
realpath:
|
|
123553
|
+
lstat: promisify3(lstat3),
|
|
123554
|
+
realpath: promisify3(realpath),
|
|
123131
123555
|
createReadStream,
|
|
123132
|
-
readdir:
|
|
123556
|
+
readdir: promisify3(readdir5),
|
|
123133
123557
|
sendError
|
|
123134
123558
|
}, methods);
|
|
123135
123559
|
module.exports = async (request2, response, config2 = {}, methods = {}) => {
|
|
@@ -123490,7 +123914,7 @@ var init_port_utils = () => {};
|
|
|
123490
123914
|
// ../api/src/services/pty-session.ts
|
|
123491
123915
|
import { chmodSync, statSync as statSync3 } from "node:fs";
|
|
123492
123916
|
import { createRequire as createRequire3 } from "node:module";
|
|
123493
|
-
import { dirname as
|
|
123917
|
+
import { dirname as dirname7, join as join9 } from "node:path";
|
|
123494
123918
|
import * as pty from "node-pty";
|
|
123495
123919
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
123496
123920
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
@@ -123522,9 +123946,9 @@ function ensureNodePtySpawnHelperExecutable() {
|
|
|
123522
123946
|
const helperCandidates = new Set;
|
|
123523
123947
|
try {
|
|
123524
123948
|
const packageJsonPath = require2.resolve("node-pty/package.json");
|
|
123525
|
-
helperCandidates.add(
|
|
123949
|
+
helperCandidates.add(join9(dirname7(packageJsonPath), "prebuilds", `darwin-${process.arch}`, "spawn-helper"));
|
|
123526
123950
|
} catch {}
|
|
123527
|
-
const bundledDistHelperPath =
|
|
123951
|
+
const bundledDistHelperPath = join9(dirname7(fileURLToPath4(import.meta.url)), "prebuilds", `darwin-${process.arch}`, "spawn-helper");
|
|
123528
123952
|
helperCandidates.add(bundledDistHelperPath);
|
|
123529
123953
|
for (const helperPath of helperCandidates) {
|
|
123530
123954
|
try {
|
|
@@ -123727,19 +124151,19 @@ var init_pty_session = __esm(() => {
|
|
|
123727
124151
|
});
|
|
123728
124152
|
|
|
123729
124153
|
// ../api/src/server/terminal-ws.ts
|
|
123730
|
-
import { dirname as
|
|
123731
|
-
import { existsSync as
|
|
124154
|
+
import { dirname as dirname8, resolve as resolve23, sep as sep6 } from "node:path";
|
|
124155
|
+
import { existsSync as existsSync15, statSync as statSync4 } from "node:fs";
|
|
123732
124156
|
function validateCwd(cwd2, root) {
|
|
123733
124157
|
if (!cwd2 || typeof cwd2 !== "string")
|
|
123734
124158
|
return null;
|
|
123735
124159
|
const resolved = resolve23(cwd2);
|
|
123736
124160
|
const resolvedRoot = resolve23(root);
|
|
123737
|
-
const parentDir =
|
|
124161
|
+
const parentDir = dirname8(resolvedRoot) + sep6;
|
|
123738
124162
|
const isWithinRoot2 = resolved === resolvedRoot || resolved.startsWith(resolvedRoot + sep6);
|
|
123739
124163
|
const isSibling = resolved.startsWith(parentDir);
|
|
123740
124164
|
if (!isWithinRoot2 && !isSibling)
|
|
123741
124165
|
return null;
|
|
123742
|
-
if (!
|
|
124166
|
+
if (!existsSync15(resolved))
|
|
123743
124167
|
return null;
|
|
123744
124168
|
try {
|
|
123745
124169
|
if (!statSync4(resolved).isDirectory())
|
|
@@ -123940,10 +124364,10 @@ __export(exports_http, {
|
|
|
123940
124364
|
startServer: () => startServer
|
|
123941
124365
|
});
|
|
123942
124366
|
import { createServer as createServer2 } from "node:http";
|
|
123943
|
-
import { existsSync as
|
|
124367
|
+
import { existsSync as existsSync16 } from "node:fs";
|
|
123944
124368
|
import { createReadStream } from "node:fs";
|
|
123945
124369
|
import { stat as stat2 } from "node:fs/promises";
|
|
123946
|
-
import { extname as
|
|
124370
|
+
import { extname as extname3, resolve as resolve24, sep as sep7 } from "node:path";
|
|
123947
124371
|
async function startServer(options2) {
|
|
123948
124372
|
const startedAt = Date.now();
|
|
123949
124373
|
const taskFileWatch = createTaskFileWatchService(options2.root);
|
|
@@ -123965,7 +124389,7 @@ async function startServer(options2) {
|
|
|
123965
124389
|
logger.error(`tRPC request failed ${JSON.stringify(details, (_key, value) => value === undefined ? "[undefined]" : value)}`);
|
|
123966
124390
|
}
|
|
123967
124391
|
});
|
|
123968
|
-
const hasUi = Boolean(options2.uiRoot &&
|
|
124392
|
+
const hasUi = Boolean(options2.uiRoot && existsSync16(options2.uiRoot));
|
|
123969
124393
|
const server = createServer2(async (req, res) => {
|
|
123970
124394
|
const url2 = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
|
|
123971
124395
|
if (url2.pathname === "/api/health/live") {
|
|
@@ -124187,7 +124611,7 @@ function safeDecode3(value) {
|
|
|
124187
124611
|
}
|
|
124188
124612
|
}
|
|
124189
124613
|
function guessContentType(absolutePath) {
|
|
124190
|
-
const ext =
|
|
124614
|
+
const ext = extname3(absolutePath).toLowerCase();
|
|
124191
124615
|
switch (ext) {
|
|
124192
124616
|
case ".png":
|
|
124193
124617
|
return "image/png";
|