@amistio/cli 0.1.14 → 0.1.16
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/index.js +162 -36
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { createHash as createHash7, randomUUID } from "node:crypto";
|
|
5
5
|
import { writeFile as writeFile9 } from "node:fs/promises";
|
|
6
6
|
import os7 from "node:os";
|
|
7
|
-
import
|
|
7
|
+
import path15 from "node:path";
|
|
8
8
|
import { Command } from "commander";
|
|
9
9
|
|
|
10
10
|
// ../shared/src/schemas.ts
|
|
@@ -773,6 +773,9 @@ var projectContextRepoPathSchema = z.string().trim().min(1).max(300).refine((val
|
|
|
773
773
|
}
|
|
774
774
|
return !value.split(/[\\/]+/).includes("..");
|
|
775
775
|
}, "Path must be repository-relative without traversal");
|
|
776
|
+
var projectContextCitationSchema = assistantCitationSchema.extend({
|
|
777
|
+
repoPath: projectContextRepoPathSchema.optional()
|
|
778
|
+
});
|
|
776
779
|
var projectContextCoverageSchema = z.object({
|
|
777
780
|
status: projectContextFreshnessSchema.default("missing"),
|
|
778
781
|
sliceCount: z.number().int().nonnegative().default(0),
|
|
@@ -789,7 +792,7 @@ var projectContextSliceSchema = z.object({
|
|
|
789
792
|
repoPaths: z.array(projectContextRepoPathSchema).max(80).default([]),
|
|
790
793
|
ownerHints: z.array(z.string().trim().min(1).max(160)).max(20).default([]),
|
|
791
794
|
tags: z.array(z.string().trim().min(1).max(80)).max(30).default([]),
|
|
792
|
-
citations: z.array(
|
|
795
|
+
citations: z.array(projectContextCitationSchema).default([]),
|
|
793
796
|
dependsOn: z.array(z.string().trim().min(1).max(160)).max(50).default([]),
|
|
794
797
|
freshness: projectContextFreshnessSchema.default("fresh"),
|
|
795
798
|
confidence: z.number().min(0).max(1).default(0.6),
|
|
@@ -803,7 +806,7 @@ var projectContextEntitySchema = z.object({
|
|
|
803
806
|
summary: z.string().trim().min(1).max(1200).optional(),
|
|
804
807
|
aliases: z.array(z.string().trim().min(1).max(200)).default([]),
|
|
805
808
|
sliceIds: z.array(z.string().trim().min(1).max(160)).default([]),
|
|
806
|
-
citations: z.array(
|
|
809
|
+
citations: z.array(projectContextCitationSchema).default([]),
|
|
807
810
|
confidence: z.number().min(0).max(1).default(0.6)
|
|
808
811
|
});
|
|
809
812
|
var projectContextRelationSchema = z.object({
|
|
@@ -812,7 +815,7 @@ var projectContextRelationSchema = z.object({
|
|
|
812
815
|
fromId: z.string().trim().min(1).max(200),
|
|
813
816
|
toId: z.string().trim().min(1).max(200),
|
|
814
817
|
summary: z.string().trim().min(1).max(1200),
|
|
815
|
-
citations: z.array(
|
|
818
|
+
citations: z.array(projectContextCitationSchema).default([]),
|
|
816
819
|
confidence: z.number().min(0).max(1).default(0.6)
|
|
817
820
|
});
|
|
818
821
|
var projectSystemDiagramStatusSchema = z.enum(["draft", "proposed", "approved", "stale", "archived"]);
|
|
@@ -829,7 +832,7 @@ var projectSystemDiagramNodeSchema = z.object({
|
|
|
829
832
|
lane: z.string().trim().min(1).max(120).optional(),
|
|
830
833
|
sliceIds: z.array(z.string().trim().min(1).max(160)).default([]),
|
|
831
834
|
entityIds: z.array(z.string().trim().min(1).max(200)).default([]),
|
|
832
|
-
citations: z.array(
|
|
835
|
+
citations: z.array(projectContextCitationSchema).min(1),
|
|
833
836
|
confidence: z.number().min(0).max(1).default(0.6),
|
|
834
837
|
freshness: projectContextFreshnessSchema.default("fresh")
|
|
835
838
|
});
|
|
@@ -840,7 +843,7 @@ var projectSystemDiagramEdgeSchema = z.object({
|
|
|
840
843
|
relationType: knowledgeRelationTypeSchema.default("mentions"),
|
|
841
844
|
label: z.string().trim().min(1).max(120).optional(),
|
|
842
845
|
summary: z.string().trim().min(1).max(1200),
|
|
843
|
-
citations: z.array(
|
|
846
|
+
citations: z.array(projectContextCitationSchema).min(1),
|
|
844
847
|
confidence: z.number().min(0).max(1).default(0.6),
|
|
845
848
|
freshness: projectContextFreshnessSchema.default("fresh")
|
|
846
849
|
});
|
|
@@ -849,7 +852,7 @@ var projectSystemDiagramGroupSchema = z.object({
|
|
|
849
852
|
label: z.string().trim().min(1).max(120),
|
|
850
853
|
kind: projectSystemDiagramGroupKindSchema.default("group"),
|
|
851
854
|
summary: z.string().trim().min(1).max(1200).optional(),
|
|
852
|
-
citations: z.array(
|
|
855
|
+
citations: z.array(projectContextCitationSchema).default([])
|
|
853
856
|
});
|
|
854
857
|
var projectSystemDiagramViewSchema = z.object({
|
|
855
858
|
viewId: z.string().trim().min(1).max(160),
|
|
@@ -871,7 +874,7 @@ var projectSystemDiagramGraphManifestSchema = z.object({
|
|
|
871
874
|
edges: z.array(projectSystemDiagramEdgeSchema).default([]),
|
|
872
875
|
groups: z.array(projectSystemDiagramGroupSchema).default([]),
|
|
873
876
|
views: z.array(projectSystemDiagramViewSchema).min(1),
|
|
874
|
-
citations: z.array(
|
|
877
|
+
citations: z.array(projectContextCitationSchema).default([]),
|
|
875
878
|
unknowns: z.array(z.string().trim().min(1).max(300)).default([]),
|
|
876
879
|
warnings: z.array(z.string().trim().min(1).max(600)).default([])
|
|
877
880
|
});
|
|
@@ -957,7 +960,7 @@ var projectContextPackSchema = z.object({
|
|
|
957
960
|
slices: z.array(projectContextSliceSchema).default([]),
|
|
958
961
|
entities: z.array(projectContextEntitySchema).default([]),
|
|
959
962
|
relations: z.array(projectContextRelationSchema).default([]),
|
|
960
|
-
citations: z.array(
|
|
963
|
+
citations: z.array(projectContextCitationSchema).default([]),
|
|
961
964
|
freshnessWarnings: z.array(z.string().trim().min(1).max(600)).default([]),
|
|
962
965
|
tokenEstimate: z.number().int().nonnegative().default(0),
|
|
963
966
|
generatedAt: isoDateTimeSchema
|
|
@@ -2382,8 +2385,8 @@ var toolSessionMutationSchema = z3.object({
|
|
|
2382
2385
|
});
|
|
2383
2386
|
function resolveApiUrl(apiUrl, urlPath) {
|
|
2384
2387
|
const base = apiUrl.endsWith("/") ? apiUrl.slice(0, -1) : apiUrl;
|
|
2385
|
-
const
|
|
2386
|
-
return new URL(`${base}${
|
|
2388
|
+
const path16 = urlPath.startsWith("/") ? urlPath : `/${urlPath}`;
|
|
2389
|
+
return new URL(`${base}${path16}`);
|
|
2387
2390
|
}
|
|
2388
2391
|
|
|
2389
2392
|
// src/orchestrator.ts
|
|
@@ -4371,6 +4374,7 @@ function defaultSessionStorePath() {
|
|
|
4371
4374
|
}
|
|
4372
4375
|
|
|
4373
4376
|
// src/work-runner.ts
|
|
4377
|
+
import path10 from "node:path";
|
|
4374
4378
|
var generationResultStart = "AMISTIO_BRAIN_GENERATION_RESULT_START";
|
|
4375
4379
|
var generationResultEnd = "AMISTIO_BRAIN_GENERATION_RESULT_END";
|
|
4376
4380
|
var assistantAnswerStart = "AMISTIO_ASSISTANT_ANSWER_START";
|
|
@@ -4385,6 +4389,8 @@ var appEvaluationStart = "AMISTIO_APP_EVALUATION_START";
|
|
|
4385
4389
|
var appEvaluationEnd = "AMISTIO_APP_EVALUATION_END";
|
|
4386
4390
|
var projectContextRefreshStart = "AMISTIO_PROJECT_CONTEXT_REFRESH_START";
|
|
4387
4391
|
var projectContextRefreshEnd = "AMISTIO_PROJECT_CONTEXT_REFRESH_END";
|
|
4392
|
+
var validProjectContextEntityTypes = /* @__PURE__ */ new Set(["project", "system", "component", "domain", "tool", "decision", "feature", "risk", "team", "workflow", "unknown"]);
|
|
4393
|
+
var validProjectContextRelationTypes = /* @__PURE__ */ new Set(["uses", "depends_on", "decides", "supersedes", "touches", "blocks", "implements", "mentions"]);
|
|
4388
4394
|
function createWorkExecutionPrompt(workItem, context) {
|
|
4389
4395
|
if (workItem.workKind === "brainGeneration") {
|
|
4390
4396
|
return createBrainGenerationPrompt(workItem);
|
|
@@ -4491,6 +4497,7 @@ function createProjectContextRefreshPrompt(workItem, context) {
|
|
|
4491
4497
|
"- Prefer summaries, repository-relative paths, short citations, tags, and freshness status over raw source excerpts.",
|
|
4492
4498
|
"- Mark stale or missing areas explicitly instead of guessing.",
|
|
4493
4499
|
"- Keep repoPaths repository-relative; never include /absolute paths or ../ traversal.",
|
|
4500
|
+
"- If local inspection prints a path inside this checkout, convert it to the repository-relative path before returning JSON.",
|
|
4494
4501
|
"",
|
|
4495
4502
|
"## Data Safety",
|
|
4496
4503
|
"",
|
|
@@ -4947,7 +4954,7 @@ function parseAppEvaluationScanResult(output) {
|
|
|
4947
4954
|
const parsed = JSON.parse(stripJsonFence(payload));
|
|
4948
4955
|
return appEvaluationScanResultSchema.parse(parsed);
|
|
4949
4956
|
}
|
|
4950
|
-
function parseProjectContextRefreshResult(output) {
|
|
4957
|
+
function parseProjectContextRefreshResult(output, options = {}) {
|
|
4951
4958
|
const start = output.indexOf(projectContextRefreshStart);
|
|
4952
4959
|
const end = output.indexOf(projectContextRefreshEnd, start + projectContextRefreshStart.length);
|
|
4953
4960
|
if (start === -1 || end === -1 || end <= start) {
|
|
@@ -4955,7 +4962,8 @@ function parseProjectContextRefreshResult(output) {
|
|
|
4955
4962
|
}
|
|
4956
4963
|
const payload = output.slice(start + projectContextRefreshStart.length, end).trim();
|
|
4957
4964
|
const parsed = JSON.parse(stripJsonFence(payload));
|
|
4958
|
-
|
|
4965
|
+
const normalized = normalizeProjectContextRefreshPaths(normalizeProjectContextRefreshEnums(parsed), options);
|
|
4966
|
+
return projectContextRefreshResultSchema.parse(normalized);
|
|
4959
4967
|
}
|
|
4960
4968
|
function projectContextRefreshSubmissionFailureSummary(result) {
|
|
4961
4969
|
if (result.refresh.status !== "failed" && result.workItem.status !== "failed") {
|
|
@@ -5019,6 +5027,122 @@ function createBrainGenerationPrompt(workItem) {
|
|
|
5019
5027
|
"Do not put Markdown fences around the markers. Do not claim implementation is complete."
|
|
5020
5028
|
].join("\n");
|
|
5021
5029
|
}
|
|
5030
|
+
function normalizeProjectContextRefreshEnums(value) {
|
|
5031
|
+
if (!isObjectRecord(value)) {
|
|
5032
|
+
return value;
|
|
5033
|
+
}
|
|
5034
|
+
const normalized = { ...value };
|
|
5035
|
+
if (Array.isArray(normalized.entities)) {
|
|
5036
|
+
normalized.entities = normalized.entities.map((entity) => {
|
|
5037
|
+
if (!isObjectRecord(entity)) {
|
|
5038
|
+
return entity;
|
|
5039
|
+
}
|
|
5040
|
+
const normalizedEntity = { ...entity };
|
|
5041
|
+
normalizedEntity.entityType = normalizeProjectContextEntityType(entity.entityType);
|
|
5042
|
+
return normalizedEntity;
|
|
5043
|
+
});
|
|
5044
|
+
}
|
|
5045
|
+
if (Array.isArray(normalized.relations)) {
|
|
5046
|
+
normalized.relations = normalized.relations.map((relation) => {
|
|
5047
|
+
if (!isObjectRecord(relation)) {
|
|
5048
|
+
return relation;
|
|
5049
|
+
}
|
|
5050
|
+
const normalizedRelation = { ...relation };
|
|
5051
|
+
normalizedRelation.relationType = normalizeProjectContextRelationType(relation.relationType);
|
|
5052
|
+
return normalizedRelation;
|
|
5053
|
+
});
|
|
5054
|
+
}
|
|
5055
|
+
return normalized;
|
|
5056
|
+
}
|
|
5057
|
+
function normalizeProjectContextRefreshPaths(value, options) {
|
|
5058
|
+
if (!isObjectRecord(value)) {
|
|
5059
|
+
return value;
|
|
5060
|
+
}
|
|
5061
|
+
const normalized = { ...value };
|
|
5062
|
+
if (Array.isArray(normalized.slices)) {
|
|
5063
|
+
normalized.slices = normalized.slices.map((slice) => normalizeProjectContextSlicePaths(slice, options));
|
|
5064
|
+
}
|
|
5065
|
+
if (Array.isArray(normalized.entities)) {
|
|
5066
|
+
normalized.entities = normalized.entities.map((entity) => normalizeProjectContextCitationPaths(entity, options));
|
|
5067
|
+
}
|
|
5068
|
+
if (Array.isArray(normalized.relations)) {
|
|
5069
|
+
normalized.relations = normalized.relations.map((relation) => normalizeProjectContextCitationPaths(relation, options));
|
|
5070
|
+
}
|
|
5071
|
+
return normalized;
|
|
5072
|
+
}
|
|
5073
|
+
function normalizeProjectContextSlicePaths(value, options) {
|
|
5074
|
+
if (!isObjectRecord(value)) {
|
|
5075
|
+
return value;
|
|
5076
|
+
}
|
|
5077
|
+
const normalized = normalizeProjectContextCitationPaths(value, options);
|
|
5078
|
+
if (Array.isArray(normalized.repoPaths)) {
|
|
5079
|
+
normalized.repoPaths = normalized.repoPaths.map((repoPath) => typeof repoPath === "string" ? normalizeProjectContextRepoPath(repoPath, options) : repoPath);
|
|
5080
|
+
}
|
|
5081
|
+
return normalized;
|
|
5082
|
+
}
|
|
5083
|
+
function normalizeProjectContextCitationPaths(value, options) {
|
|
5084
|
+
if (!isObjectRecord(value)) {
|
|
5085
|
+
return value;
|
|
5086
|
+
}
|
|
5087
|
+
const normalized = { ...value };
|
|
5088
|
+
if (Array.isArray(normalized.citations)) {
|
|
5089
|
+
normalized.citations = normalized.citations.map((citation) => {
|
|
5090
|
+
if (!isObjectRecord(citation)) {
|
|
5091
|
+
return citation;
|
|
5092
|
+
}
|
|
5093
|
+
const normalizedCitation = { ...citation };
|
|
5094
|
+
if (typeof normalizedCitation.repoPath === "string") {
|
|
5095
|
+
normalizedCitation.repoPath = normalizeProjectContextRepoPath(normalizedCitation.repoPath, options);
|
|
5096
|
+
}
|
|
5097
|
+
return normalizedCitation;
|
|
5098
|
+
});
|
|
5099
|
+
}
|
|
5100
|
+
return normalized;
|
|
5101
|
+
}
|
|
5102
|
+
function normalizeProjectContextRepoPath(value, options) {
|
|
5103
|
+
const trimmed = value.trim();
|
|
5104
|
+
if (!trimmed || /^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(trimmed) || /^file:/i.test(trimmed) || /^[A-Za-z]:($|[^\\/])/.test(trimmed)) {
|
|
5105
|
+
throwUnsafeProjectContextPath();
|
|
5106
|
+
}
|
|
5107
|
+
const absolute = trimmed.startsWith("/") || trimmed.startsWith("\\\\") || path10.isAbsolute(trimmed) || path10.win32.isAbsolute(trimmed);
|
|
5108
|
+
if (!absolute) {
|
|
5109
|
+
return normalizeRelativeProjectContextPath(trimmed);
|
|
5110
|
+
}
|
|
5111
|
+
if (!options.repositoryRoot) {
|
|
5112
|
+
throwUnsafeProjectContextPath();
|
|
5113
|
+
}
|
|
5114
|
+
const useWindowsPathRules = path10.win32.isAbsolute(trimmed) && !trimmed.startsWith("/");
|
|
5115
|
+
const relativePath = useWindowsPathRules ? path10.win32.relative(path10.win32.resolve(options.repositoryRoot), path10.win32.resolve(trimmed)) : path10.relative(path10.resolve(options.repositoryRoot), path10.resolve(trimmed));
|
|
5116
|
+
return normalizeRelativeProjectContextPath(relativePath);
|
|
5117
|
+
}
|
|
5118
|
+
function normalizeRelativeProjectContextPath(value) {
|
|
5119
|
+
const normalized = value.trim().replace(/\\/g, "/");
|
|
5120
|
+
const segments = normalized.split("/").filter((segment) => segment.length > 0 && segment !== ".");
|
|
5121
|
+
if (!segments.length || normalized.startsWith("/") || normalized === "~" || normalized.startsWith("~/") || /^[A-Za-z]:/.test(normalized) || segments.includes("..")) {
|
|
5122
|
+
throwUnsafeProjectContextPath();
|
|
5123
|
+
}
|
|
5124
|
+
return segments.join("/");
|
|
5125
|
+
}
|
|
5126
|
+
function throwUnsafeProjectContextPath() {
|
|
5127
|
+
throw new Error("Project context refresh contains an unsafe repository path.");
|
|
5128
|
+
}
|
|
5129
|
+
function normalizeProjectContextEntityType(value) {
|
|
5130
|
+
if (typeof value !== "string") {
|
|
5131
|
+
return "unknown";
|
|
5132
|
+
}
|
|
5133
|
+
const normalized = value.trim().toLowerCase();
|
|
5134
|
+
return validProjectContextEntityTypes.has(normalized) ? normalized : "unknown";
|
|
5135
|
+
}
|
|
5136
|
+
function normalizeProjectContextRelationType(value) {
|
|
5137
|
+
if (typeof value !== "string") {
|
|
5138
|
+
return "mentions";
|
|
5139
|
+
}
|
|
5140
|
+
const normalized = value.trim().toLowerCase();
|
|
5141
|
+
return validProjectContextRelationTypes.has(normalized) ? normalized : "mentions";
|
|
5142
|
+
}
|
|
5143
|
+
function isObjectRecord(value) {
|
|
5144
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5145
|
+
}
|
|
5022
5146
|
function artifactFormatPreferenceInstructions(preference) {
|
|
5023
5147
|
if (preference === "html") {
|
|
5024
5148
|
return "The user chose HTML. Generate .html artifacts under docs/html/<folder>/ and set contentFormat to html.";
|
|
@@ -5194,7 +5318,7 @@ function roundNumber(value, digits) {
|
|
|
5194
5318
|
import { execFile as execFile4 } from "node:child_process";
|
|
5195
5319
|
import { createHash as createHash6 } from "node:crypto";
|
|
5196
5320
|
import { readdir as readdir4, readFile as readFile8, stat as stat4 } from "node:fs/promises";
|
|
5197
|
-
import
|
|
5321
|
+
import path11 from "node:path";
|
|
5198
5322
|
import { promisify as promisify4 } from "node:util";
|
|
5199
5323
|
var execFileAsync4 = promisify4(execFile4);
|
|
5200
5324
|
var defaultMaxFileKb = 256;
|
|
@@ -5213,12 +5337,12 @@ var documentFolderByType = {
|
|
|
5213
5337
|
workflow: "docs/workflows"
|
|
5214
5338
|
};
|
|
5215
5339
|
async function inspectLocalRepository(rootDir, defaultBranch) {
|
|
5216
|
-
const requestedRoot =
|
|
5340
|
+
const requestedRoot = path11.resolve(rootDir);
|
|
5217
5341
|
const root = await runGit2(["-C", requestedRoot, "rev-parse", "--show-toplevel"]).catch(() => requestedRoot);
|
|
5218
5342
|
const detectedBranch = await runGit2(["-C", root, "symbolic-ref", "--quiet", "--short", "HEAD"]).catch(() => defaultBranch);
|
|
5219
5343
|
const originUrl = await runGit2(["-C", root, "remote", "get-url", "origin"]).catch(() => void 0);
|
|
5220
5344
|
const parsedCloneUrl = originUrl ? parseOptionalOriginCloneUrl(originUrl) : void 0;
|
|
5221
|
-
const repoName = (parsedCloneUrl?.repoName ??
|
|
5345
|
+
const repoName = (parsedCloneUrl?.repoName ?? path11.basename(root)) || "repository";
|
|
5222
5346
|
const fingerprintSeed = parsedCloneUrl ? `origin:${parsedCloneUrl.normalizedKey}` : `repo:${repoName}:${detectedBranch || defaultBranch}`;
|
|
5223
5347
|
return {
|
|
5224
5348
|
rootDir: root,
|
|
@@ -5230,7 +5354,7 @@ async function inspectLocalRepository(rootDir, defaultBranch) {
|
|
|
5230
5354
|
};
|
|
5231
5355
|
}
|
|
5232
5356
|
async function scanLegacyDocuments(options) {
|
|
5233
|
-
const rootDir =
|
|
5357
|
+
const rootDir = path11.resolve(options.rootDir);
|
|
5234
5358
|
const maxBytes = (options.maxFileKb ?? defaultMaxFileKb) * 1024;
|
|
5235
5359
|
const skipped = [];
|
|
5236
5360
|
const candidates = [];
|
|
@@ -5250,7 +5374,7 @@ async function scanLegacyDocuments(options) {
|
|
|
5250
5374
|
skipped.push({ repoPath, reason: "excluded" });
|
|
5251
5375
|
continue;
|
|
5252
5376
|
}
|
|
5253
|
-
const fullPath =
|
|
5377
|
+
const fullPath = path11.join(rootDir, ...repoPath.split("/"));
|
|
5254
5378
|
const fileStat = await stat4(fullPath).catch(() => void 0);
|
|
5255
5379
|
if (!fileStat?.isFile()) {
|
|
5256
5380
|
skipped.push({ repoPath, reason: "unreadable" });
|
|
@@ -5352,8 +5476,8 @@ async function listRepositoryPaths(rootDir) {
|
|
|
5352
5476
|
async function walkRepository(rootDir, directory, files) {
|
|
5353
5477
|
const entries = await readdir4(directory, { withFileTypes: true }).catch(() => []);
|
|
5354
5478
|
for (const entry of entries) {
|
|
5355
|
-
const fullPath =
|
|
5356
|
-
const repoPath = normalizeRepoPath4(
|
|
5479
|
+
const fullPath = path11.join(directory, entry.name);
|
|
5480
|
+
const repoPath = normalizeRepoPath4(path11.relative(rootDir, fullPath));
|
|
5357
5481
|
if (entry.isDirectory()) {
|
|
5358
5482
|
if (!excludedDirectoryNames.has(entry.name)) {
|
|
5359
5483
|
await walkRepository(rootDir, fullPath, files);
|
|
@@ -5419,9 +5543,9 @@ function uniqueDestinationPath(basePath, sourcePath, usedPaths) {
|
|
|
5419
5543
|
usedPaths.add(basePath);
|
|
5420
5544
|
return basePath;
|
|
5421
5545
|
}
|
|
5422
|
-
const extension =
|
|
5423
|
-
const directory =
|
|
5424
|
-
const basename =
|
|
5546
|
+
const extension = path11.posix.extname(basePath) || ".md";
|
|
5547
|
+
const directory = path11.posix.dirname(basePath);
|
|
5548
|
+
const basename = path11.posix.basename(basePath, extension);
|
|
5425
5549
|
const uniquePath = `${directory}/${basename}-${hashText(sourcePath, 8)}${extension}`;
|
|
5426
5550
|
usedPaths.add(uniquePath);
|
|
5427
5551
|
return uniquePath;
|
|
@@ -5440,7 +5564,7 @@ function inferTitle2(content, repoPath) {
|
|
|
5440
5564
|
if (heading) return heading;
|
|
5441
5565
|
const htmlHeading = body.match(/<h1\b[^>]*>([\s\S]*?)<\/h1>/i)?.[1]?.replace(/<[^>]+>/g, "").trim();
|
|
5442
5566
|
if (htmlHeading) return htmlHeading;
|
|
5443
|
-
const basename =
|
|
5567
|
+
const basename = path11.posix.basename(repoPath, path11.posix.extname(repoPath)).replace(/[-_]+/g, " ").trim();
|
|
5444
5568
|
return titleCase(basename || "Imported Document");
|
|
5445
5569
|
}
|
|
5446
5570
|
function stripFrontmatter(content) {
|
|
@@ -5474,7 +5598,7 @@ async function runGit2(args) {
|
|
|
5474
5598
|
|
|
5475
5599
|
// src/runner-actions.ts
|
|
5476
5600
|
import { spawn as spawn4 } from "node:child_process";
|
|
5477
|
-
import
|
|
5601
|
+
import path12 from "node:path";
|
|
5478
5602
|
function buildBackgroundRunnerArgs(options) {
|
|
5479
5603
|
const args = [
|
|
5480
5604
|
"run",
|
|
@@ -5484,7 +5608,7 @@ function buildBackgroundRunnerArgs(options) {
|
|
|
5484
5608
|
"--runner-id",
|
|
5485
5609
|
options.runnerId,
|
|
5486
5610
|
"--root",
|
|
5487
|
-
|
|
5611
|
+
path12.resolve(options.root),
|
|
5488
5612
|
"--session",
|
|
5489
5613
|
options.session,
|
|
5490
5614
|
"--interval-seconds",
|
|
@@ -5602,7 +5726,7 @@ function truncateProcessOutput(value) {
|
|
|
5602
5726
|
// src/git-worktree.ts
|
|
5603
5727
|
import { execFile as execFile5 } from "node:child_process";
|
|
5604
5728
|
import { mkdir as mkdir9, stat as stat5 } from "node:fs/promises";
|
|
5605
|
-
import
|
|
5729
|
+
import path13 from "node:path";
|
|
5606
5730
|
import { promisify as promisify5 } from "node:util";
|
|
5607
5731
|
var execFileAsync5 = promisify5(execFile5);
|
|
5608
5732
|
function needsGitWorktreeIsolation(workItem) {
|
|
@@ -5631,7 +5755,7 @@ async function prepareGitWorktreeIsolation(rootDir, workItem) {
|
|
|
5631
5755
|
await assertExistingWorktree(worktreePath, identity.branch);
|
|
5632
5756
|
return { ...identity, baseRevision, worktreePath };
|
|
5633
5757
|
}
|
|
5634
|
-
await mkdir9(
|
|
5758
|
+
await mkdir9(path13.dirname(worktreePath), { recursive: true });
|
|
5635
5759
|
const branchExists = await gitCommandSucceeds(repoRoot, ["show-ref", "--verify", "--quiet", `refs/heads/${identity.branch}`]);
|
|
5636
5760
|
const worktreeArgs = branchExists ? ["worktree", "add", worktreePath, identity.branch] : ["worktree", "add", "-b", identity.branch, worktreePath, baseRevision];
|
|
5637
5761
|
await gitOutput(repoRoot, worktreeArgs).catch((error) => {
|
|
@@ -5640,9 +5764,9 @@ async function prepareGitWorktreeIsolation(rootDir, workItem) {
|
|
|
5640
5764
|
return { ...identity, baseRevision, worktreePath };
|
|
5641
5765
|
}
|
|
5642
5766
|
function localWorktreePath(repoRoot, worktreeKey) {
|
|
5643
|
-
const repoName =
|
|
5767
|
+
const repoName = path13.basename(repoRoot);
|
|
5644
5768
|
const worktreeSlug = worktreeKey.split("/").filter(Boolean).pop() ?? "work";
|
|
5645
|
-
return
|
|
5769
|
+
return path13.join(path13.dirname(repoRoot), `${repoName}.worktrees`, worktreeSlug);
|
|
5646
5770
|
}
|
|
5647
5771
|
async function assertExistingWorktree(worktreePath, branch) {
|
|
5648
5772
|
await gitOutput(worktreePath, ["rev-parse", "--is-inside-work-tree"]);
|
|
@@ -5689,7 +5813,7 @@ function errorMessage2(error) {
|
|
|
5689
5813
|
|
|
5690
5814
|
// src/implementation-handoff.ts
|
|
5691
5815
|
import { execFile as execFile6 } from "node:child_process";
|
|
5692
|
-
import
|
|
5816
|
+
import path14 from "node:path";
|
|
5693
5817
|
import { promisify as promisify6 } from "node:util";
|
|
5694
5818
|
var execFileAsync6 = promisify6(execFile6);
|
|
5695
5819
|
async function completeImplementationHandoff(input) {
|
|
@@ -5775,7 +5899,7 @@ async function cleanupWorktree(run, input) {
|
|
|
5775
5899
|
return { status: "failed", message: "Cleanup skipped because the worktree is not clean after PR handoff." };
|
|
5776
5900
|
}
|
|
5777
5901
|
try {
|
|
5778
|
-
await gitOutput2(run, input.primaryRepoRoot ||
|
|
5902
|
+
await gitOutput2(run, input.primaryRepoRoot || path14.dirname(input.worktreePath), ["worktree", "remove", input.worktreePath]);
|
|
5779
5903
|
return { status: "completed" };
|
|
5780
5904
|
} catch (error) {
|
|
5781
5905
|
return { status: "failed", message: `Cleanup failed: ${safeErrorMessage(error)}` };
|
|
@@ -6264,7 +6388,7 @@ program.command("run").description("Claim and run approved Amistio work locally"
|
|
|
6264
6388
|
projectId: context.metadata.amistioProjectId,
|
|
6265
6389
|
repositoryLinkId: context.metadata.repositoryLinkId,
|
|
6266
6390
|
runnerId,
|
|
6267
|
-
rootDir:
|
|
6391
|
+
rootDir: path15.resolve(options.root),
|
|
6268
6392
|
apiUrl: options.apiUrl,
|
|
6269
6393
|
args: buildBackgroundRunnerArgs(resolvedOptions)
|
|
6270
6394
|
});
|
|
@@ -6436,7 +6560,7 @@ runnerService.command("install").description("Install a user-level startup servi
|
|
|
6436
6560
|
projectId: context.metadata.amistioProjectId,
|
|
6437
6561
|
repositoryLinkId: context.metadata.repositoryLinkId,
|
|
6438
6562
|
runnerId,
|
|
6439
|
-
rootDir:
|
|
6563
|
+
rootDir: path15.resolve(options.root),
|
|
6440
6564
|
apiUrl: options.apiUrl,
|
|
6441
6565
|
args,
|
|
6442
6566
|
platform
|
|
@@ -6908,6 +7032,7 @@ async function runNextWorkItem({
|
|
|
6908
7032
|
return await finalizeProjectContextRefreshWork({
|
|
6909
7033
|
apiClient,
|
|
6910
7034
|
durationMs: Date.now() - startedAt,
|
|
7035
|
+
executionRoot,
|
|
6911
7036
|
projectId,
|
|
6912
7037
|
repositoryLinkId,
|
|
6913
7038
|
runnerId,
|
|
@@ -7762,6 +7887,7 @@ ${toolResult.stderr}`);
|
|
|
7762
7887
|
async function finalizeProjectContextRefreshWork({
|
|
7763
7888
|
apiClient,
|
|
7764
7889
|
durationMs,
|
|
7890
|
+
executionRoot,
|
|
7765
7891
|
projectId,
|
|
7766
7892
|
repositoryLinkId,
|
|
7767
7893
|
runnerId,
|
|
@@ -7776,7 +7902,7 @@ async function finalizeProjectContextRefreshWork({
|
|
|
7776
7902
|
if (toolResult.exitCode === 0) {
|
|
7777
7903
|
try {
|
|
7778
7904
|
refreshResult = parseProjectContextRefreshResult(`${toolResult.stdout}
|
|
7779
|
-
${toolResult.stderr}
|
|
7905
|
+
${toolResult.stderr}`, { repositoryRoot: executionRoot });
|
|
7780
7906
|
} catch (error) {
|
|
7781
7907
|
refreshError = errorMessage3(error);
|
|
7782
7908
|
}
|
|
@@ -8153,7 +8279,7 @@ function parseReasoningEffort(value) {
|
|
|
8153
8279
|
throw new Error(`Expected reasoning effort auto, low, medium, high, or xhigh; received ${value}.`);
|
|
8154
8280
|
}
|
|
8155
8281
|
function inferRepoName(root) {
|
|
8156
|
-
return
|
|
8282
|
+
return path15.basename(path15.resolve(root)) || "repository";
|
|
8157
8283
|
}
|
|
8158
8284
|
function createRepoFingerprint(accountId, projectId, repositoryLinkId) {
|
|
8159
8285
|
return createHash7("sha256").update(`${accountId}:${projectId}:${repositoryLinkId}`).digest("hex");
|