schub 0.1.15 → 0.1.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/server.js +479 -16
- package/dist/dashboard/assets/{EquationComponent-B8bIWTs4.js → EquationComponent-rkyM4LAk.js} +1 -1
- package/dist/dashboard/assets/index-DgZ7OKyk.js +396 -0
- package/dist/dashboard/assets/index-PQXzu0rH.css +1 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/index.js +290 -244
- package/dist/services/runtime.js +17291 -0
- package/package.json +6 -5
- package/skills/create-ticket/SKILL.md +1 -1
- package/skills/{implement-task → implement-ticket}/SKILL.md +6 -10
- package/dist/dashboard/assets/index-CrVPkqrB.css +0 -1
- package/dist/dashboard/assets/index-DhqXvDTi.js +0 -396
package/dist/api/server.js
CHANGED
|
@@ -32152,6 +32152,136 @@ var createFilesService = (db, storageRoot) => {
|
|
|
32152
32152
|
};
|
|
32153
32153
|
};
|
|
32154
32154
|
|
|
32155
|
+
// ../schub-services/src/services/git-diff.ts
|
|
32156
|
+
import { exec } from "node:child_process";
|
|
32157
|
+
import { promisify } from "node:util";
|
|
32158
|
+
var execAsync = promisify(exec);
|
|
32159
|
+
function normalizeHeaderPath(input) {
|
|
32160
|
+
if (!input)
|
|
32161
|
+
return null;
|
|
32162
|
+
const token = input.split("\t")[0].trim();
|
|
32163
|
+
if (token === "/dev/null")
|
|
32164
|
+
return null;
|
|
32165
|
+
let normalized = token;
|
|
32166
|
+
if (normalized.startsWith("a/") || normalized.startsWith("b/")) {
|
|
32167
|
+
normalized = normalized.slice(2);
|
|
32168
|
+
}
|
|
32169
|
+
normalized = normalized.replace(/^\/+/, "").replace(/\\/g, "/");
|
|
32170
|
+
return normalized;
|
|
32171
|
+
}
|
|
32172
|
+
var createGitDiffService = () => {
|
|
32173
|
+
const parseDiff = (diffText) => {
|
|
32174
|
+
if (!diffText || typeof diffText !== "string")
|
|
32175
|
+
return [];
|
|
32176
|
+
const changes = new Map;
|
|
32177
|
+
let currentPath = null;
|
|
32178
|
+
let lastMinusHeader = null;
|
|
32179
|
+
let inHunk = false;
|
|
32180
|
+
const lines = diffText.split(/\r?\n/);
|
|
32181
|
+
for (const line of lines) {
|
|
32182
|
+
if (line.startsWith("--- ")) {
|
|
32183
|
+
lastMinusHeader = normalizeHeaderPath(line.slice(4));
|
|
32184
|
+
inHunk = false;
|
|
32185
|
+
continue;
|
|
32186
|
+
}
|
|
32187
|
+
if (line.startsWith("+++ ")) {
|
|
32188
|
+
const plusPath = normalizeHeaderPath(line.slice(4));
|
|
32189
|
+
currentPath = plusPath ?? lastMinusHeader;
|
|
32190
|
+
if (currentPath && !changes.has(currentPath)) {
|
|
32191
|
+
changes.set(currentPath, { additions: 0, deletions: 0 });
|
|
32192
|
+
}
|
|
32193
|
+
inHunk = false;
|
|
32194
|
+
continue;
|
|
32195
|
+
}
|
|
32196
|
+
if (!currentPath)
|
|
32197
|
+
continue;
|
|
32198
|
+
if (line.startsWith("@@")) {
|
|
32199
|
+
inHunk = true;
|
|
32200
|
+
continue;
|
|
32201
|
+
}
|
|
32202
|
+
if (!inHunk)
|
|
32203
|
+
continue;
|
|
32204
|
+
if (line.startsWith("+") && !(line.startsWith("+++ ") || line === "+++")) {
|
|
32205
|
+
const current = changes.get(currentPath);
|
|
32206
|
+
if (current)
|
|
32207
|
+
current.additions += 1;
|
|
32208
|
+
continue;
|
|
32209
|
+
}
|
|
32210
|
+
if (line.startsWith("-") && !(line.startsWith("--- ") || line === "---")) {
|
|
32211
|
+
const current = changes.get(currentPath);
|
|
32212
|
+
if (current)
|
|
32213
|
+
current.deletions += 1;
|
|
32214
|
+
}
|
|
32215
|
+
}
|
|
32216
|
+
return Array.from(changes.entries()).map(([filePath, { additions, deletions }]) => ({
|
|
32217
|
+
filePath,
|
|
32218
|
+
additions,
|
|
32219
|
+
deletions
|
|
32220
|
+
}));
|
|
32221
|
+
};
|
|
32222
|
+
const isGitRepo = async (repoPath) => {
|
|
32223
|
+
try {
|
|
32224
|
+
const { stdout } = await execAsync("git rev-parse --git-dir", {
|
|
32225
|
+
cwd: repoPath,
|
|
32226
|
+
timeout: 5000
|
|
32227
|
+
});
|
|
32228
|
+
return stdout.trim().length > 0;
|
|
32229
|
+
} catch {
|
|
32230
|
+
return false;
|
|
32231
|
+
}
|
|
32232
|
+
};
|
|
32233
|
+
const executeDiff = async (repoPath, args) => {
|
|
32234
|
+
try {
|
|
32235
|
+
const { stdout } = await execAsync(`git diff ${args.join(" ")}`, {
|
|
32236
|
+
cwd: repoPath,
|
|
32237
|
+
timeout: 30000,
|
|
32238
|
+
maxBuffer: 10 * 1024 * 1024
|
|
32239
|
+
});
|
|
32240
|
+
return { success: true, diff: stdout };
|
|
32241
|
+
} catch (error48) {
|
|
32242
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
32243
|
+
return { success: false, error: message };
|
|
32244
|
+
}
|
|
32245
|
+
};
|
|
32246
|
+
const getUnstagedDiff = async (repoPath) => {
|
|
32247
|
+
const result = await executeDiff(repoPath, ["HEAD"]);
|
|
32248
|
+
if (!result.success) {
|
|
32249
|
+
throw new Error(`Failed to get unstaged diff: ${result.error}`);
|
|
32250
|
+
}
|
|
32251
|
+
return result.diff;
|
|
32252
|
+
};
|
|
32253
|
+
const getStagedDiff = async (repoPath) => {
|
|
32254
|
+
const result = await executeDiff(repoPath, ["--cached", "HEAD"]);
|
|
32255
|
+
if (!result.success) {
|
|
32256
|
+
throw new Error(`Failed to get staged diff: ${result.error}`);
|
|
32257
|
+
}
|
|
32258
|
+
return result.diff;
|
|
32259
|
+
};
|
|
32260
|
+
const getAllDiff = async (repoPath) => {
|
|
32261
|
+
return getUnstagedDiff(repoPath);
|
|
32262
|
+
};
|
|
32263
|
+
const getDiffByMode = async (repoPath, mode) => {
|
|
32264
|
+
switch (mode) {
|
|
32265
|
+
case "unstaged":
|
|
32266
|
+
return getUnstagedDiff(repoPath);
|
|
32267
|
+
case "staged":
|
|
32268
|
+
return getStagedDiff(repoPath);
|
|
32269
|
+
case "all":
|
|
32270
|
+
return getAllDiff(repoPath);
|
|
32271
|
+
default:
|
|
32272
|
+
throw new Error(`Invalid diff mode: ${mode}`);
|
|
32273
|
+
}
|
|
32274
|
+
};
|
|
32275
|
+
return {
|
|
32276
|
+
parseDiff,
|
|
32277
|
+
isGitRepo,
|
|
32278
|
+
getUnstagedDiff,
|
|
32279
|
+
getStagedDiff,
|
|
32280
|
+
getAllDiff,
|
|
32281
|
+
getDiffByMode
|
|
32282
|
+
};
|
|
32283
|
+
};
|
|
32284
|
+
|
|
32155
32285
|
// ../schub-services/src/services/opencode.ts
|
|
32156
32286
|
import { spawn } from "node:child_process";
|
|
32157
32287
|
import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
|
|
@@ -33895,6 +34025,7 @@ var createServices = (config2 = {}) => {
|
|
|
33895
34025
|
const agents = createAgentsService();
|
|
33896
34026
|
const docs = createDocsService();
|
|
33897
34027
|
const files2 = createFilesService(db, storageRoot);
|
|
34028
|
+
const gitDiff = createGitDiffService();
|
|
33898
34029
|
const opencode = createOpencodeService();
|
|
33899
34030
|
const proposalStatuses = createProposalStatusesService(db);
|
|
33900
34031
|
const projects2 = createProjectsService(db);
|
|
@@ -33909,6 +34040,7 @@ var createServices = (config2 = {}) => {
|
|
|
33909
34040
|
agents,
|
|
33910
34041
|
docs,
|
|
33911
34042
|
files: files2,
|
|
34043
|
+
gitDiff,
|
|
33912
34044
|
opencode,
|
|
33913
34045
|
proposalStatuses,
|
|
33914
34046
|
projects: projects2,
|
|
@@ -34795,6 +34927,230 @@ var registerImageRoutes = (router) => {
|
|
|
34795
34927
|
]);
|
|
34796
34928
|
};
|
|
34797
34929
|
|
|
34930
|
+
// ../schub-api/src/routes/project-template-assets.ts
|
|
34931
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "node:fs";
|
|
34932
|
+
import { dirname as dirname2, join as join4, resolve as resolve2 } from "node:path";
|
|
34933
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
34934
|
+
var PROJECT_TEMPLATE_TYPES = ["template", "skill"];
|
|
34935
|
+
var projectTemplateAssetSchema = exports_external.object({
|
|
34936
|
+
id: exports_external.string(),
|
|
34937
|
+
project_id: exports_external.string().nullable(),
|
|
34938
|
+
name: exports_external.string(),
|
|
34939
|
+
template_type: exports_external.enum(PROJECT_TEMPLATE_TYPES),
|
|
34940
|
+
content: exports_external.string(),
|
|
34941
|
+
created_at: exports_external.string(),
|
|
34942
|
+
updated_at: exports_external.string()
|
|
34943
|
+
});
|
|
34944
|
+
var projectIdParamsSchema = exports_external.object({
|
|
34945
|
+
project_id: exports_external.string()
|
|
34946
|
+
});
|
|
34947
|
+
var projectTemplateAssetParamsSchema = exports_external.object({
|
|
34948
|
+
project_id: exports_external.string(),
|
|
34949
|
+
asset_id: exports_external.string()
|
|
34950
|
+
});
|
|
34951
|
+
var updateProjectTemplateAssetSchema = exports_external.object({
|
|
34952
|
+
content: exports_external.string()
|
|
34953
|
+
});
|
|
34954
|
+
var DEFAULT_PROJECT_TEMPLATE_ASSETS = [
|
|
34955
|
+
{
|
|
34956
|
+
name: "create-proposal/proposal-template.md",
|
|
34957
|
+
template_type: "template",
|
|
34958
|
+
source_path: "templates/create-proposal/proposal-template.md"
|
|
34959
|
+
},
|
|
34960
|
+
{
|
|
34961
|
+
name: "create-proposal/cookbook-template.md",
|
|
34962
|
+
template_type: "template",
|
|
34963
|
+
source_path: "templates/create-proposal/cookbook-template.md"
|
|
34964
|
+
},
|
|
34965
|
+
{
|
|
34966
|
+
name: "create-proposal/adr-template.md",
|
|
34967
|
+
template_type: "template",
|
|
34968
|
+
source_path: "templates/create-proposal/adr-template.md"
|
|
34969
|
+
},
|
|
34970
|
+
{
|
|
34971
|
+
name: "create-ticket/ticket-template.md",
|
|
34972
|
+
template_type: "template",
|
|
34973
|
+
source_path: "templates/create-ticket/ticket-template.md"
|
|
34974
|
+
},
|
|
34975
|
+
{
|
|
34976
|
+
name: "create-tasks/task-template.md",
|
|
34977
|
+
template_type: "template",
|
|
34978
|
+
source_path: "templates/create-tasks/task-template.md"
|
|
34979
|
+
},
|
|
34980
|
+
{
|
|
34981
|
+
name: "review-proposal/review-me-template.md",
|
|
34982
|
+
template_type: "template",
|
|
34983
|
+
source_path: "templates/review-proposal/review-me-template.md"
|
|
34984
|
+
},
|
|
34985
|
+
{
|
|
34986
|
+
name: "review-proposal/q&a-template.md",
|
|
34987
|
+
template_type: "template",
|
|
34988
|
+
source_path: "templates/review-proposal/q&a-template.md"
|
|
34989
|
+
},
|
|
34990
|
+
{ name: "create-proposal/SKILL.md", template_type: "skill", source_path: "skills/create-proposal/SKILL.md" },
|
|
34991
|
+
{ name: "create-ticket/SKILL.md", template_type: "skill", source_path: "skills/create-ticket/SKILL.md" },
|
|
34992
|
+
{
|
|
34993
|
+
name: "create-tickets-for-proposal/SKILL.md",
|
|
34994
|
+
template_type: "skill",
|
|
34995
|
+
source_path: "skills/create-tickets-for-proposal/SKILL.md"
|
|
34996
|
+
},
|
|
34997
|
+
{ name: "implement-ticket/SKILL.md", template_type: "skill", source_path: "skills/implement-ticket/SKILL.md" },
|
|
34998
|
+
{ name: "review-proposal/SKILL.md", template_type: "skill", source_path: "skills/review-proposal/SKILL.md" }
|
|
34999
|
+
];
|
|
35000
|
+
var templateTypeOrder = new Map(PROJECT_TEMPLATE_TYPES.map((type, index) => [type, index]));
|
|
35001
|
+
var isProjectTemplateType = (value) => PROJECT_TEMPLATE_TYPES.includes(value);
|
|
35002
|
+
var isSchubPackageRoot = (rootPath) => existsSync3(join4(rootPath, "templates")) && existsSync3(join4(rootPath, "skills"));
|
|
35003
|
+
var resolveBundledSchubRoot = () => {
|
|
35004
|
+
const moduleRoot = resolve2(dirname2(fileURLToPath2(import.meta.url)), "../../../schub");
|
|
35005
|
+
const workspaceRoot = resolve2(process.cwd(), "packages", "schub");
|
|
35006
|
+
const siblingRoot = resolve2(process.cwd(), "..", "schub");
|
|
35007
|
+
const localRoot = resolve2(process.cwd());
|
|
35008
|
+
const candidates = [moduleRoot, workspaceRoot, siblingRoot, localRoot];
|
|
35009
|
+
return candidates.find(isSchubPackageRoot) ?? null;
|
|
35010
|
+
};
|
|
35011
|
+
var loadBundledTemplateAssets = () => {
|
|
35012
|
+
const schubRoot = resolveBundledSchubRoot();
|
|
35013
|
+
if (!schubRoot)
|
|
35014
|
+
return [];
|
|
35015
|
+
return DEFAULT_PROJECT_TEMPLATE_ASSETS.flatMap((asset) => {
|
|
35016
|
+
const storagePath = join4(schubRoot, asset.source_path);
|
|
35017
|
+
if (!existsSync3(storagePath)) {
|
|
35018
|
+
return [];
|
|
35019
|
+
}
|
|
35020
|
+
return [
|
|
35021
|
+
{
|
|
35022
|
+
name: asset.name,
|
|
35023
|
+
template_type: asset.template_type,
|
|
35024
|
+
content: readFileSync2(storagePath, "utf8")
|
|
35025
|
+
}
|
|
35026
|
+
];
|
|
35027
|
+
});
|
|
35028
|
+
};
|
|
35029
|
+
var sortAssets = (assets) => [...assets].sort((left, right) => {
|
|
35030
|
+
const leftType = templateTypeOrder.get(left.template_type) ?? Number.MAX_SAFE_INTEGER;
|
|
35031
|
+
const rightType = templateTypeOrder.get(right.template_type) ?? Number.MAX_SAFE_INTEGER;
|
|
35032
|
+
if (leftType !== rightType) {
|
|
35033
|
+
return leftType - rightType;
|
|
35034
|
+
}
|
|
35035
|
+
return left.name.localeCompare(right.name);
|
|
35036
|
+
});
|
|
35037
|
+
var seedMissingAssets = (context, projectId) => {
|
|
35038
|
+
const services = context.get("services");
|
|
35039
|
+
const existing = services.templates.list().filter((asset) => asset.project_id === projectId && isProjectTemplateType(asset.template_type));
|
|
35040
|
+
const existingKeys = new Set(existing.map((asset) => `${asset.template_type}:${asset.name}`));
|
|
35041
|
+
const defaults = loadBundledTemplateAssets();
|
|
35042
|
+
defaults.forEach((asset) => {
|
|
35043
|
+
const key = `${asset.template_type}:${asset.name}`;
|
|
35044
|
+
if (existingKeys.has(key))
|
|
35045
|
+
return;
|
|
35046
|
+
services.templates.create({
|
|
35047
|
+
project_id: projectId,
|
|
35048
|
+
name: asset.name,
|
|
35049
|
+
template_type: asset.template_type,
|
|
35050
|
+
content: asset.content
|
|
35051
|
+
});
|
|
35052
|
+
});
|
|
35053
|
+
};
|
|
35054
|
+
var registerProjectTemplateAssetRoutes = (router) => {
|
|
35055
|
+
const listRoute = createRoute({
|
|
35056
|
+
method: "get",
|
|
35057
|
+
path: "/projects/:project_id/template-assets",
|
|
35058
|
+
tags: ["Projects"],
|
|
35059
|
+
summary: "List project template and skill assets",
|
|
35060
|
+
request: {
|
|
35061
|
+
params: projectIdParamsSchema
|
|
35062
|
+
},
|
|
35063
|
+
responses: {
|
|
35064
|
+
200: {
|
|
35065
|
+
description: "Project template assets",
|
|
35066
|
+
content: {
|
|
35067
|
+
"application/json": {
|
|
35068
|
+
schema: apiSuccessSchema(exports_external.array(projectTemplateAssetSchema))
|
|
35069
|
+
}
|
|
35070
|
+
}
|
|
35071
|
+
},
|
|
35072
|
+
404: {
|
|
35073
|
+
description: "Project not found",
|
|
35074
|
+
content: {
|
|
35075
|
+
"application/json": {
|
|
35076
|
+
schema: apiErrorSchema
|
|
35077
|
+
}
|
|
35078
|
+
}
|
|
35079
|
+
}
|
|
35080
|
+
}
|
|
35081
|
+
});
|
|
35082
|
+
const listHandler = (c) => {
|
|
35083
|
+
const { project_id } = c.req.valid("param");
|
|
35084
|
+
const services = c.get("services");
|
|
35085
|
+
const project = services.projects.get(project_id);
|
|
35086
|
+
if (!project) {
|
|
35087
|
+
return c.json(errorResponse("Project not found"), 404);
|
|
35088
|
+
}
|
|
35089
|
+
seedMissingAssets(c, project_id);
|
|
35090
|
+
const assets = sortAssets(services.templates.list().filter((asset) => asset.project_id === project_id && isProjectTemplateType(asset.template_type)));
|
|
35091
|
+
return c.json(okResponse(assets), 200);
|
|
35092
|
+
};
|
|
35093
|
+
router.openapi(listRoute, listHandler);
|
|
35094
|
+
const updateRoute = createRoute({
|
|
35095
|
+
method: "put",
|
|
35096
|
+
path: "/projects/:project_id/template-assets/:asset_id",
|
|
35097
|
+
tags: ["Projects"],
|
|
35098
|
+
summary: "Update project template or skill asset",
|
|
35099
|
+
request: {
|
|
35100
|
+
params: projectTemplateAssetParamsSchema,
|
|
35101
|
+
body: {
|
|
35102
|
+
content: {
|
|
35103
|
+
"application/json": {
|
|
35104
|
+
schema: updateProjectTemplateAssetSchema
|
|
35105
|
+
}
|
|
35106
|
+
}
|
|
35107
|
+
}
|
|
35108
|
+
},
|
|
35109
|
+
responses: {
|
|
35110
|
+
200: {
|
|
35111
|
+
description: "Updated project template asset",
|
|
35112
|
+
content: {
|
|
35113
|
+
"application/json": {
|
|
35114
|
+
schema: apiSuccessSchema(projectTemplateAssetSchema)
|
|
35115
|
+
}
|
|
35116
|
+
}
|
|
35117
|
+
},
|
|
35118
|
+
404: {
|
|
35119
|
+
description: "Asset not found",
|
|
35120
|
+
content: {
|
|
35121
|
+
"application/json": {
|
|
35122
|
+
schema: apiErrorSchema
|
|
35123
|
+
}
|
|
35124
|
+
}
|
|
35125
|
+
}
|
|
35126
|
+
}
|
|
35127
|
+
});
|
|
35128
|
+
const updateHandler = (c) => {
|
|
35129
|
+
const { project_id, asset_id } = c.req.valid("param");
|
|
35130
|
+
const { content } = c.req.valid("json");
|
|
35131
|
+
const services = c.get("services");
|
|
35132
|
+
const project = services.projects.get(project_id);
|
|
35133
|
+
if (!project) {
|
|
35134
|
+
return c.json(errorResponse("Project not found"), 404);
|
|
35135
|
+
}
|
|
35136
|
+
const existing = services.templates.get(asset_id);
|
|
35137
|
+
if (!existing || existing.project_id !== project_id || !isProjectTemplateType(existing.template_type)) {
|
|
35138
|
+
return c.json(errorResponse("Template asset not found"), 404);
|
|
35139
|
+
}
|
|
35140
|
+
const updated = services.templates.update(asset_id, {
|
|
35141
|
+
project_id,
|
|
35142
|
+
name: existing.name,
|
|
35143
|
+
template_type: existing.template_type,
|
|
35144
|
+
content
|
|
35145
|
+
});
|
|
35146
|
+
if (!updated) {
|
|
35147
|
+
return c.json(errorResponse("Template asset not found"), 404);
|
|
35148
|
+
}
|
|
35149
|
+
return c.json(okResponse(updated), 200);
|
|
35150
|
+
};
|
|
35151
|
+
router.openapi(updateRoute, updateHandler);
|
|
35152
|
+
};
|
|
35153
|
+
|
|
34798
35154
|
// ../schub-api/src/routes/projects.ts
|
|
34799
35155
|
var projectSchema = exports_external.object({
|
|
34800
35156
|
id: exports_external.string(),
|
|
@@ -34821,7 +35177,7 @@ var createProjectSchema = exports_external.object({
|
|
|
34821
35177
|
var updateProjectSchema = exports_external.object({
|
|
34822
35178
|
name: exports_external.string().min(1)
|
|
34823
35179
|
});
|
|
34824
|
-
var
|
|
35180
|
+
var projectIdParamsSchema2 = exports_external.object({
|
|
34825
35181
|
id: exports_external.string()
|
|
34826
35182
|
});
|
|
34827
35183
|
var projectRepoParamsSchema = exports_external.object({
|
|
@@ -34891,7 +35247,7 @@ var registerProjectRoutes = (router, upgradeWebSocket) => {
|
|
|
34891
35247
|
tags: ["Projects"],
|
|
34892
35248
|
summary: "Get project",
|
|
34893
35249
|
request: {
|
|
34894
|
-
params:
|
|
35250
|
+
params: projectIdParamsSchema2
|
|
34895
35251
|
},
|
|
34896
35252
|
responses: {
|
|
34897
35253
|
200: {
|
|
@@ -34927,7 +35283,7 @@ var registerProjectRoutes = (router, upgradeWebSocket) => {
|
|
|
34927
35283
|
tags: ["Projects"],
|
|
34928
35284
|
summary: "Update project",
|
|
34929
35285
|
request: {
|
|
34930
|
-
params:
|
|
35286
|
+
params: projectIdParamsSchema2,
|
|
34931
35287
|
body: {
|
|
34932
35288
|
content: {
|
|
34933
35289
|
"application/json": {
|
|
@@ -34971,7 +35327,7 @@ var registerProjectRoutes = (router, upgradeWebSocket) => {
|
|
|
34971
35327
|
tags: ["Projects"],
|
|
34972
35328
|
summary: "Delete project",
|
|
34973
35329
|
request: {
|
|
34974
|
-
params:
|
|
35330
|
+
params: projectIdParamsSchema2
|
|
34975
35331
|
},
|
|
34976
35332
|
responses: {
|
|
34977
35333
|
204: {
|
|
@@ -35002,7 +35358,7 @@ var registerProjectRoutes = (router, upgradeWebSocket) => {
|
|
|
35002
35358
|
tags: ["Projects"],
|
|
35003
35359
|
summary: "List project repositories",
|
|
35004
35360
|
request: {
|
|
35005
|
-
params:
|
|
35361
|
+
params: projectIdParamsSchema2
|
|
35006
35362
|
},
|
|
35007
35363
|
responses: {
|
|
35008
35364
|
200: {
|
|
@@ -35027,7 +35383,7 @@ var registerProjectRoutes = (router, upgradeWebSocket) => {
|
|
|
35027
35383
|
tags: ["Projects"],
|
|
35028
35384
|
summary: "Add project repository",
|
|
35029
35385
|
request: {
|
|
35030
|
-
params:
|
|
35386
|
+
params: projectIdParamsSchema2,
|
|
35031
35387
|
body: {
|
|
35032
35388
|
content: {
|
|
35033
35389
|
"application/json": {
|
|
@@ -35625,8 +35981,8 @@ var registerProposalRoutes = (router) => {
|
|
|
35625
35981
|
// ../schub-api/src/routes/repos.ts
|
|
35626
35982
|
import { execFile } from "node:child_process";
|
|
35627
35983
|
import { mkdir as mkdir2 } from "node:fs/promises";
|
|
35628
|
-
import { join as
|
|
35629
|
-
import { promisify } from "node:util";
|
|
35984
|
+
import { join as join5, resolve as resolve3 } from "node:path";
|
|
35985
|
+
import { promisify as promisify2 } from "node:util";
|
|
35630
35986
|
var repoSchema2 = exports_external.object({
|
|
35631
35987
|
id: exports_external.string(),
|
|
35632
35988
|
name: exports_external.string(),
|
|
@@ -35656,7 +36012,7 @@ var repoIdParamsSchema = exports_external.object({
|
|
|
35656
36012
|
var updateRepoSchema = exports_external.object({
|
|
35657
36013
|
display_name: exports_external.string().nullable().optional()
|
|
35658
36014
|
});
|
|
35659
|
-
var execFileAsync =
|
|
36015
|
+
var execFileAsync = promisify2(execFile);
|
|
35660
36016
|
var normalizeBranchDate = (value) => {
|
|
35661
36017
|
if (!value) {
|
|
35662
36018
|
return new Date().toISOString();
|
|
@@ -35803,9 +36159,9 @@ var registerRepoRoutes = (router) => {
|
|
|
35803
36159
|
});
|
|
35804
36160
|
const initHandler = async (c) => {
|
|
35805
36161
|
const payload = c.req.valid("json");
|
|
35806
|
-
const repoPath =
|
|
36162
|
+
const repoPath = resolve3(payload.parent_path, payload.folder_name);
|
|
35807
36163
|
await mkdir2(repoPath, { recursive: true });
|
|
35808
|
-
await mkdir2(
|
|
36164
|
+
await mkdir2(join5(repoPath, ".git"), { recursive: true });
|
|
35809
36165
|
const repo = c.get("services").repos.register({
|
|
35810
36166
|
path: repoPath,
|
|
35811
36167
|
display_name: payload.display_name ?? payload.folder_name
|
|
@@ -36837,8 +37193,8 @@ var registerTicketStatusRoutes = (router) => {
|
|
|
36837
37193
|
|
|
36838
37194
|
// ../schub-api/src/routes/tickets.ts
|
|
36839
37195
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
36840
|
-
import { existsSync as
|
|
36841
|
-
import { join as
|
|
37196
|
+
import { existsSync as existsSync4, mkdirSync } from "node:fs";
|
|
37197
|
+
import { join as join6 } from "node:path";
|
|
36842
37198
|
var runGit = (cwd, args) => {
|
|
36843
37199
|
return spawnSync2("git", args, {
|
|
36844
37200
|
cwd,
|
|
@@ -36852,16 +37208,16 @@ var createAttemptWorktree = (options) => {
|
|
|
36852
37208
|
throw new Error("Repository is not a git repository.");
|
|
36853
37209
|
}
|
|
36854
37210
|
const gitRoot = gitRootResult.stdout.trim();
|
|
36855
|
-
const worktreePath =
|
|
37211
|
+
const worktreePath = join6(gitRoot, ".schub", "worktrees", options.ticketShorthand, `attempt-${options.attemptNumber}`);
|
|
36856
37212
|
const branchName = `ticket/${options.ticketShorthand}/attempt-${options.attemptNumber}`;
|
|
36857
|
-
if (
|
|
37213
|
+
if (existsSync4(worktreePath)) {
|
|
36858
37214
|
throw new Error(`Worktree path already exists: ${worktreePath}`);
|
|
36859
37215
|
}
|
|
36860
37216
|
const branchCheck = runGit(gitRoot, ["show-ref", "--verify", "--quiet", `refs/heads/${branchName}`]);
|
|
36861
37217
|
if (branchCheck.status === 0) {
|
|
36862
37218
|
throw new Error(`Branch ${branchName} already exists.`);
|
|
36863
37219
|
}
|
|
36864
|
-
mkdirSync(
|
|
37220
|
+
mkdirSync(join6(gitRoot, ".schub", "worktrees", options.ticketShorthand), { recursive: true });
|
|
36865
37221
|
const worktreeArgs = ["worktree", "add", "-b", branchName, worktreePath];
|
|
36866
37222
|
const baseBranch = options.baseBranch?.trim();
|
|
36867
37223
|
if (baseBranch) {
|
|
@@ -37484,7 +37840,113 @@ var registerWorkspaceImageRoutes = (router) => {
|
|
|
37484
37840
|
};
|
|
37485
37841
|
|
|
37486
37842
|
// ../schub-api/src/routes/workspaces.ts
|
|
37843
|
+
var workspaceDiffQuerySchema = exports_external.object({
|
|
37844
|
+
mode: exports_external.enum(["unstaged", "staged", "all"])
|
|
37845
|
+
});
|
|
37846
|
+
var workspaceIdParamsSchema = exports_external.object({
|
|
37847
|
+
workspaceId: exports_external.string().uuid()
|
|
37848
|
+
});
|
|
37849
|
+
var fileChangeSchema = exports_external.object({
|
|
37850
|
+
filePath: exports_external.string(),
|
|
37851
|
+
additions: exports_external.number(),
|
|
37852
|
+
deletions: exports_external.number()
|
|
37853
|
+
});
|
|
37854
|
+
var workspaceDiffDataSchema = exports_external.object({
|
|
37855
|
+
workspace_id: exports_external.string(),
|
|
37856
|
+
mode: exports_external.enum(["unstaged", "staged", "all"]),
|
|
37857
|
+
diff_text: exports_external.string(),
|
|
37858
|
+
files: exports_external.array(fileChangeSchema),
|
|
37859
|
+
totals: exports_external.object({
|
|
37860
|
+
additions: exports_external.number(),
|
|
37861
|
+
deletions: exports_external.number(),
|
|
37862
|
+
file_count: exports_external.number()
|
|
37863
|
+
})
|
|
37864
|
+
});
|
|
37487
37865
|
var registerWorkspaceRoutes = (router) => {
|
|
37866
|
+
const diffRoute = createRoute({
|
|
37867
|
+
method: "get",
|
|
37868
|
+
path: "/workspaces/:workspaceId/diff",
|
|
37869
|
+
tags: ["Workspaces"],
|
|
37870
|
+
summary: "Get workspace diff",
|
|
37871
|
+
request: {
|
|
37872
|
+
params: workspaceIdParamsSchema,
|
|
37873
|
+
query: workspaceDiffQuerySchema
|
|
37874
|
+
},
|
|
37875
|
+
responses: {
|
|
37876
|
+
200: {
|
|
37877
|
+
description: "Workspace diff",
|
|
37878
|
+
content: {
|
|
37879
|
+
"application/json": {
|
|
37880
|
+
schema: apiSuccessSchema(workspaceDiffDataSchema)
|
|
37881
|
+
}
|
|
37882
|
+
}
|
|
37883
|
+
},
|
|
37884
|
+
400: {
|
|
37885
|
+
description: "Bad request",
|
|
37886
|
+
content: {
|
|
37887
|
+
"application/json": {
|
|
37888
|
+
schema: apiErrorSchema
|
|
37889
|
+
}
|
|
37890
|
+
}
|
|
37891
|
+
},
|
|
37892
|
+
404: {
|
|
37893
|
+
description: "Workspace or repository not found",
|
|
37894
|
+
content: {
|
|
37895
|
+
"application/json": {
|
|
37896
|
+
schema: apiErrorSchema
|
|
37897
|
+
}
|
|
37898
|
+
}
|
|
37899
|
+
},
|
|
37900
|
+
500: {
|
|
37901
|
+
description: "Failed to get diff",
|
|
37902
|
+
content: {
|
|
37903
|
+
"application/json": {
|
|
37904
|
+
schema: apiErrorSchema
|
|
37905
|
+
}
|
|
37906
|
+
}
|
|
37907
|
+
}
|
|
37908
|
+
}
|
|
37909
|
+
});
|
|
37910
|
+
const diffHandler = async (c) => {
|
|
37911
|
+
const { workspaceId } = c.req.valid("param");
|
|
37912
|
+
const { mode } = c.req.valid("query");
|
|
37913
|
+
const services = c.get("services");
|
|
37914
|
+
const workspace = services.workspaces.get(workspaceId);
|
|
37915
|
+
if (!workspace) {
|
|
37916
|
+
return c.json(errorResponse("Workspace not found"), 404);
|
|
37917
|
+
}
|
|
37918
|
+
if (!workspace.repo_id) {
|
|
37919
|
+
return c.json(errorResponse("Workspace has no associated repository"), 400);
|
|
37920
|
+
}
|
|
37921
|
+
const repo = services.repos.get(workspace.repo_id);
|
|
37922
|
+
if (!repo) {
|
|
37923
|
+
return c.json(errorResponse("Repository not found"), 404);
|
|
37924
|
+
}
|
|
37925
|
+
const isGitRepo2 = await services.gitDiff.isGitRepo(repo.path);
|
|
37926
|
+
if (!isGitRepo2) {
|
|
37927
|
+
return c.json(errorResponse("Path is not a git repository"), 400);
|
|
37928
|
+
}
|
|
37929
|
+
try {
|
|
37930
|
+
const diffText = await services.gitDiff.getDiffByMode(repo.path, mode);
|
|
37931
|
+
const files2 = services.gitDiff.parseDiff(diffText);
|
|
37932
|
+
const totals = files2.reduce((acc, file2) => ({
|
|
37933
|
+
additions: acc.additions + file2.additions,
|
|
37934
|
+
deletions: acc.deletions + file2.deletions,
|
|
37935
|
+
file_count: acc.file_count + 1
|
|
37936
|
+
}), { additions: 0, deletions: 0, file_count: 0 });
|
|
37937
|
+
return c.json(okResponse({
|
|
37938
|
+
workspace_id: workspaceId,
|
|
37939
|
+
mode,
|
|
37940
|
+
diff_text: diffText,
|
|
37941
|
+
files: files2,
|
|
37942
|
+
totals
|
|
37943
|
+
}), 200);
|
|
37944
|
+
} catch (error48) {
|
|
37945
|
+
const message = error48 instanceof Error ? error48.message : "Failed to get diff";
|
|
37946
|
+
return c.json(errorResponse(message), 500);
|
|
37947
|
+
}
|
|
37948
|
+
};
|
|
37949
|
+
router.openapi(diffRoute, diffHandler);
|
|
37488
37950
|
registerPlaceholderRoutes(router, "Workspaces", [
|
|
37489
37951
|
{ method: "get", path: "/ticket-attempts" },
|
|
37490
37952
|
{ method: "post", path: "/ticket-attempts" },
|
|
@@ -37529,6 +37991,7 @@ var createRoutes = (options) => {
|
|
|
37529
37991
|
registerContainerRoutes(routes);
|
|
37530
37992
|
registerDocsRoutes(routes);
|
|
37531
37993
|
registerProjectRoutes(routes, options.upgradeWebSocket);
|
|
37994
|
+
registerProjectTemplateAssetRoutes(routes);
|
|
37532
37995
|
registerTicketStatusRoutes(routes);
|
|
37533
37996
|
registerProposalRoutes(routes);
|
|
37534
37997
|
registerTicketRoutes(routes);
|
package/dist/dashboard/assets/{EquationComponent-B8bIWTs4.js → EquationComponent-rkyM4LAk.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as f,r as u,k as E,j as a,o as p}from"./index-
|
|
1
|
+
import{c as f,r as u,k as E,j as a,o as p}from"./index-DgZ7OKyk.js";function x(c){const e=f.c(5),{equation:i,inline:n}=c,l=u.useRef(null);let o,t;e[0]!==i||e[1]!==n?(o=()=>{const s=l.current;s!==null&&E.render(i,s,{displayMode:!n,errorColor:"#cc0000",output:"html",strict:"warn",throwOnError:!1,trust:!1})},t=[i,n],e[0]=i,e[1]=n,e[2]=o,e[3]=t):(o=e[2],t=e[3]),u.useEffect(o,t);let r;return e[4]===Symbol.for("react.memo_cache_sentinel")?(r=a.jsxs(a.Fragment,{children:[a.jsx("img",{src:"#",alt:""}),a.jsx("span",{ref:l}),a.jsx("img",{src:"#",alt:""})]}),e[4]=r):r=e[4],r}class d extends u.Component{state={hasError:!1};static getDerivedStateFromError(){return{hasError:!0}}componentDidCatch(e){this.props.onError(e)}render(){return this.state.hasError?null:this.props.children}}function j(c){const e=f.c(8),{equation:i,inline:n}=c,[l]=p(),[o]=u.useState(i);let t;e[0]!==l?(t=m=>l._onError(m),e[0]=l,e[1]=t):t=e[1];let r;e[2]!==o||e[3]!==n?(r=a.jsx(x,{equation:o,inline:n}),e[2]=o,e[3]=n,e[4]=r):r=e[4];let s;return e[5]!==t||e[6]!==r?(s=a.jsx(d,{onError:t,children:r}),e[5]=t,e[6]=r,e[7]=s):s=e[7],s}export{j as default};
|