@inspecto-dev/plugin 0.3.10 → 0.3.11
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/astro.cjs +210 -84
- package/dist/astro.cjs.map +1 -1
- package/dist/astro.js +180 -53
- package/dist/astro.js.map +1 -1
- package/dist/index.cjs +210 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +180 -53
- package/dist/index.js.map +1 -1
- package/dist/legacy/rspack/index.cjs +210 -84
- package/dist/legacy/rspack/index.cjs.map +1 -1
- package/dist/legacy/rspack/index.js +180 -53
- package/dist/legacy/rspack/index.js.map +1 -1
- package/dist/legacy/webpack4/index.cjs +210 -84
- package/dist/legacy/webpack4/index.cjs.map +1 -1
- package/dist/legacy/webpack4/index.js +180 -53
- package/dist/legacy/webpack4/index.js.map +1 -1
- package/dist/rollup.cjs +210 -84
- package/dist/rollup.cjs.map +1 -1
- package/dist/rollup.js +180 -53
- package/dist/rollup.js.map +1 -1
- package/dist/rspack.cjs +210 -84
- package/dist/rspack.cjs.map +1 -1
- package/dist/rspack.js +180 -53
- package/dist/rspack.js.map +1 -1
- package/dist/vite.cjs +210 -84
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.js +180 -53
- package/dist/vite.js.map +1 -1
- package/dist/webpack.cjs +210 -84
- package/dist/webpack.cjs.map +1 -1
- package/dist/webpack.js +180 -53
- package/dist/webpack.js.map +1 -1
- package/package.json +2 -2
|
@@ -169,7 +169,8 @@ import { createDefu } from "defu";
|
|
|
169
169
|
import {
|
|
170
170
|
DEFAULT_PROVIDER_MODE,
|
|
171
171
|
VALID_MODES,
|
|
172
|
-
DEFAULT_INTENTS
|
|
172
|
+
DEFAULT_INTENTS,
|
|
173
|
+
isWorkflowConfig
|
|
173
174
|
} from "@inspecto-dev/types";
|
|
174
175
|
|
|
175
176
|
// src/utils/logger.ts
|
|
@@ -403,13 +404,28 @@ function resolveIntents(serverPrompts) {
|
|
|
403
404
|
);
|
|
404
405
|
continue;
|
|
405
406
|
}
|
|
406
|
-
if (
|
|
407
|
-
|
|
408
|
-
|
|
407
|
+
if (item.kind === "workflow") {
|
|
408
|
+
if (!item.prompt) {
|
|
409
|
+
configLogger.warn(`Workflow "${item.id}" missing required "prompt", skipping`);
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
result.push({
|
|
413
|
+
kind: "workflow",
|
|
414
|
+
id: item.id,
|
|
415
|
+
label: item.label ?? item.id,
|
|
416
|
+
prompt: item.prompt,
|
|
417
|
+
confirm: item.confirm ?? false,
|
|
418
|
+
enabled: item.enabled ?? true
|
|
419
|
+
});
|
|
420
|
+
} else {
|
|
421
|
+
if (!item.aiIntent) {
|
|
422
|
+
configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
result.push(
|
|
426
|
+
baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item
|
|
427
|
+
);
|
|
409
428
|
}
|
|
410
|
-
result.push(
|
|
411
|
-
baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item
|
|
412
|
-
);
|
|
413
429
|
}
|
|
414
430
|
}
|
|
415
431
|
return result;
|
|
@@ -429,26 +445,61 @@ function resolveIntents(serverPrompts) {
|
|
|
429
445
|
configLogger.warn('Intent object missing required "id" field, skipping.');
|
|
430
446
|
continue;
|
|
431
447
|
}
|
|
432
|
-
if (
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
448
|
+
if (item.kind === "workflow") {
|
|
449
|
+
if (!item.prompt) {
|
|
450
|
+
configLogger.warn(`Workflow "${item.id}" missing required "prompt", skipping`);
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
const wfConfig = {
|
|
454
|
+
kind: "workflow",
|
|
455
|
+
id: item.id,
|
|
456
|
+
label: item.label ?? item.id,
|
|
457
|
+
prompt: item.prompt,
|
|
458
|
+
confirm: item.confirm ?? false,
|
|
459
|
+
enabled: item.enabled ?? true
|
|
460
|
+
};
|
|
461
|
+
const existingIdx = merged.findIndex((i) => i.id === item.id);
|
|
462
|
+
if (existingIdx !== -1) {
|
|
463
|
+
if (item.enabled === false) {
|
|
464
|
+
merged.splice(existingIdx, 1);
|
|
465
|
+
} else {
|
|
466
|
+
merged[existingIdx] = wfConfig;
|
|
467
|
+
}
|
|
440
468
|
} else {
|
|
441
|
-
|
|
469
|
+
if (item.enabled !== false) {
|
|
470
|
+
merged.push(wfConfig);
|
|
471
|
+
}
|
|
442
472
|
}
|
|
443
473
|
} else {
|
|
444
|
-
if (item.
|
|
445
|
-
|
|
474
|
+
if (!item.aiIntent) {
|
|
475
|
+
configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
const existingIdx = merged.findIndex((i) => i.id === item.id);
|
|
479
|
+
if (existingIdx !== -1) {
|
|
480
|
+
if (item.enabled === false) {
|
|
481
|
+
merged.splice(existingIdx, 1);
|
|
482
|
+
} else {
|
|
483
|
+
merged[existingIdx] = { ...merged[existingIdx], ...item };
|
|
484
|
+
}
|
|
485
|
+
} else {
|
|
486
|
+
if (item.enabled !== false) {
|
|
487
|
+
merged.push(item);
|
|
488
|
+
}
|
|
446
489
|
}
|
|
447
490
|
}
|
|
448
491
|
}
|
|
449
492
|
}
|
|
450
493
|
return merged;
|
|
451
494
|
}
|
|
495
|
+
function resolveWorkflowSlots(intents) {
|
|
496
|
+
return intents.filter(isWorkflowConfig).filter((w) => w.enabled !== false).map((w) => ({
|
|
497
|
+
id: w.id,
|
|
498
|
+
label: w.label ?? w.id,
|
|
499
|
+
prompt: w.prompt,
|
|
500
|
+
confirm: w.confirm ?? false
|
|
501
|
+
}));
|
|
502
|
+
}
|
|
452
503
|
var watchers = [];
|
|
453
504
|
function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
|
|
454
505
|
if (isWatching) return;
|
|
@@ -678,6 +729,10 @@ function assertPathWithinIdeOpenScope(file, projectRoot) {
|
|
|
678
729
|
}
|
|
679
730
|
}
|
|
680
731
|
|
|
732
|
+
// src/server/annotation-dispatch.ts
|
|
733
|
+
import { exec } from "child_process";
|
|
734
|
+
import { promisify } from "util";
|
|
735
|
+
|
|
681
736
|
// src/server/session-store.ts
|
|
682
737
|
var DEFAULT_STATUS = "pending";
|
|
683
738
|
function createAnnotationSessionStore(options = {}) {
|
|
@@ -685,8 +740,12 @@ function createAnnotationSessionStore(options = {}) {
|
|
|
685
740
|
const listeners = /* @__PURE__ */ new Set();
|
|
686
741
|
const now = options.now ?? (() => Date.now());
|
|
687
742
|
const createId = options.createId ?? createRandomId;
|
|
688
|
-
function findNewestMatchingSession(statuses) {
|
|
689
|
-
return [...sessions.values()].filter((session) =>
|
|
743
|
+
function findNewestMatchingSession(statuses, source) {
|
|
744
|
+
return [...sessions.values()].filter((session) => {
|
|
745
|
+
if (statuses && !statuses.has(session.status)) return false;
|
|
746
|
+
if (source && session.source !== source) return false;
|
|
747
|
+
return true;
|
|
748
|
+
}).sort((left, right) => right.updatedAt - left.updatedAt)[0] ?? null;
|
|
690
749
|
}
|
|
691
750
|
function updateSessionStatus(id, status) {
|
|
692
751
|
const session = sessions.get(id);
|
|
@@ -746,7 +805,7 @@ function createAnnotationSessionStore(options = {}) {
|
|
|
746
805
|
},
|
|
747
806
|
async claimNextSession(options2 = {}) {
|
|
748
807
|
const statuses = normalizeStatuses(DEFAULT_STATUS);
|
|
749
|
-
const existingSession = findNewestMatchingSession(statuses);
|
|
808
|
+
const existingSession = findNewestMatchingSession(statuses, options2.source);
|
|
750
809
|
if (existingSession) {
|
|
751
810
|
return {
|
|
752
811
|
session: claimSession(existingSession.id, statuses),
|
|
@@ -861,6 +920,7 @@ function cloneValue(value) {
|
|
|
861
920
|
}
|
|
862
921
|
|
|
863
922
|
// src/server/annotation-dispatch.ts
|
|
923
|
+
var execAsync = promisify(exec);
|
|
864
924
|
var AnnotationDispatchError = class extends Error {
|
|
865
925
|
constructor(message, errorCode) {
|
|
866
926
|
super(message);
|
|
@@ -872,9 +932,14 @@ async function dispatchAnnotationsToAi(req, state, store = annotationSessionStor
|
|
|
872
932
|
try {
|
|
873
933
|
validateAnnotationDispatchRequest(req, state);
|
|
874
934
|
const batch = normalizeAnnotationBatch(req);
|
|
875
|
-
|
|
935
|
+
let prompt = buildAnnotationBatchPrompt(batch);
|
|
936
|
+
if (req.source === "workflow") {
|
|
937
|
+
prompt = await appendProjectMetadata(prompt, state);
|
|
938
|
+
}
|
|
876
939
|
const deliveryMode = normalizeDeliveryMode(req.deliveryMode);
|
|
877
940
|
const session = store.createSession({
|
|
941
|
+
source: req.source || "annotation",
|
|
942
|
+
...req.workflowId ? { workflowId: req.workflowId } : {},
|
|
878
943
|
instruction: batch.instruction,
|
|
879
944
|
annotations: toSessionAnnotations(batch.annotations),
|
|
880
945
|
deliveryMode,
|
|
@@ -900,6 +965,33 @@ async function dispatchAnnotationsToAi(req, state, store = annotationSessionStor
|
|
|
900
965
|
};
|
|
901
966
|
}
|
|
902
967
|
}
|
|
968
|
+
async function appendProjectMetadata(prompt, state) {
|
|
969
|
+
const lines = ["\n## Project"];
|
|
970
|
+
lines.push(`- Root: ${state.projectRoot}`);
|
|
971
|
+
try {
|
|
972
|
+
const options = {
|
|
973
|
+
cwd: state.projectRoot,
|
|
974
|
+
encoding: "utf-8",
|
|
975
|
+
timeout: 2e3
|
|
976
|
+
};
|
|
977
|
+
const { stdout: branchStdout } = await execAsync("git branch --show-current", options);
|
|
978
|
+
const branch = branchStdout.trim();
|
|
979
|
+
lines.push(`- Branch: ${branch}`);
|
|
980
|
+
const { stdout: statusStdout } = await execAsync("git status --porcelain", options);
|
|
981
|
+
const statusRaw = statusStdout.trim();
|
|
982
|
+
const entries = statusRaw ? statusRaw.split("\n") : [];
|
|
983
|
+
const staged = entries.filter((l) => l[0] !== " " && l[0] !== "?").length;
|
|
984
|
+
const unstaged = entries.filter((l) => l[1] !== " " && l[1] !== "?").length;
|
|
985
|
+
const untracked = entries.filter((l) => l[0] === "?").length;
|
|
986
|
+
lines.push(`- Status: ${staged} staged, ${unstaged} unstaged, ${untracked} untracked`);
|
|
987
|
+
} catch (err) {
|
|
988
|
+
console.warn("[inspecto] Failed to get git status for workflow:", err);
|
|
989
|
+
lines.push("- Git: unavailable or check timeout");
|
|
990
|
+
}
|
|
991
|
+
return `${prompt}
|
|
992
|
+
|
|
993
|
+
${lines.join("\n")}`;
|
|
994
|
+
}
|
|
903
995
|
function normalizeDeliveryMode(input) {
|
|
904
996
|
return input === "agent" ? "agent" : "ide";
|
|
905
997
|
}
|
|
@@ -936,7 +1028,7 @@ function toSessionSummary(session) {
|
|
|
936
1028
|
};
|
|
937
1029
|
}
|
|
938
1030
|
function validateAnnotationDispatchRequest(req, state) {
|
|
939
|
-
if (!req.annotations.length) {
|
|
1031
|
+
if (!req.annotations.length && req.source !== "workflow") {
|
|
940
1032
|
throw new AnnotationDispatchError("At least one annotation is required.", "INVALID_REQUEST");
|
|
941
1033
|
}
|
|
942
1034
|
for (const annotation of req.annotations) {
|
|
@@ -1038,6 +1130,7 @@ function getAnnotationDispatchErrorCode(error) {
|
|
|
1038
1130
|
}
|
|
1039
1131
|
|
|
1040
1132
|
// src/server/client-config.ts
|
|
1133
|
+
import { isAiIntentConfig } from "@inspecto-dev/types";
|
|
1041
1134
|
async function buildClientConfig(serverState2) {
|
|
1042
1135
|
const userConfig = loadUserConfigSync(false, serverState2.cwd, serverState2.configRoot);
|
|
1043
1136
|
const promptsConfig = await loadPromptsConfig(false, serverState2.cwd, serverState2.configRoot);
|
|
@@ -1049,11 +1142,13 @@ async function buildClientConfig(serverState2) {
|
|
|
1049
1142
|
const { scheme: _scheme, ...rest } = serverState2.ideInfo;
|
|
1050
1143
|
info = rest;
|
|
1051
1144
|
}
|
|
1145
|
+
const allIntents = resolveIntents(promptsConfig);
|
|
1052
1146
|
return {
|
|
1053
1147
|
...info,
|
|
1054
|
-
prompts:
|
|
1148
|
+
prompts: allIntents.filter(isAiIntentConfig),
|
|
1149
|
+
workflows: resolveWorkflowSlots(allIntents),
|
|
1055
1150
|
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
1056
|
-
annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "
|
|
1151
|
+
annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "agent",
|
|
1057
1152
|
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
1058
1153
|
runtimeContext: {
|
|
1059
1154
|
enabled: true,
|
|
@@ -1150,41 +1245,60 @@ import fs4 from "fs";
|
|
|
1150
1245
|
import path5 from "path";
|
|
1151
1246
|
import { execSync } from "child_process";
|
|
1152
1247
|
var serverLogger3 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
1153
|
-
function
|
|
1154
|
-
const cwd = process.cwd();
|
|
1155
|
-
let gitRoot;
|
|
1248
|
+
function resolveGitRoot(_cwd) {
|
|
1156
1249
|
try {
|
|
1157
|
-
|
|
1250
|
+
const output = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" });
|
|
1251
|
+
return typeof output === "string" ? output.trim() : null;
|
|
1158
1252
|
} catch (e) {
|
|
1159
1253
|
serverLogger3.warn("Failed to resolve git root via git rev-parse:", e);
|
|
1160
|
-
gitRoot = cwd;
|
|
1161
|
-
}
|
|
1162
|
-
const visited = /* @__PURE__ */ new Set();
|
|
1163
|
-
const search = (start, stop) => {
|
|
1164
|
-
let current = start;
|
|
1165
|
-
while (!visited.has(current)) {
|
|
1166
|
-
visited.add(current);
|
|
1167
|
-
if (fs4.existsSync(path5.join(current, ".inspecto"))) return current;
|
|
1168
|
-
if (current === stop) break;
|
|
1169
|
-
const parent = path5.dirname(current);
|
|
1170
|
-
if (parent === current) break;
|
|
1171
|
-
current = parent;
|
|
1172
|
-
}
|
|
1173
1254
|
return null;
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
function findNearestAncestorWith(start, predicate) {
|
|
1258
|
+
let current = start;
|
|
1259
|
+
while (true) {
|
|
1260
|
+
if (predicate(current)) return current;
|
|
1261
|
+
const parent = path5.dirname(current);
|
|
1262
|
+
if (parent === current) break;
|
|
1263
|
+
current = parent;
|
|
1264
|
+
}
|
|
1265
|
+
return null;
|
|
1266
|
+
}
|
|
1267
|
+
function resolveWorkspaceRoot() {
|
|
1268
|
+
const cwd = process.cwd();
|
|
1269
|
+
const inspectoRoot = findNearestAncestorWith(
|
|
1270
|
+
cwd,
|
|
1271
|
+
(dir) => fs4.existsSync(path5.join(dir, ".inspecto"))
|
|
1272
|
+
);
|
|
1273
|
+
if (inspectoRoot) return inspectoRoot;
|
|
1274
|
+
const packageRoot = findNearestAncestorWith(
|
|
1275
|
+
cwd,
|
|
1276
|
+
(dir) => fs4.existsSync(path5.join(dir, "package.json"))
|
|
1277
|
+
);
|
|
1278
|
+
if (packageRoot) return packageRoot;
|
|
1279
|
+
return resolveGitRoot(cwd) ?? cwd;
|
|
1280
|
+
}
|
|
1281
|
+
function resolveProjectRoot() {
|
|
1282
|
+
const cwd = process.cwd();
|
|
1283
|
+
const packageRoot = findNearestAncestorWith(
|
|
1284
|
+
cwd,
|
|
1285
|
+
(dir) => fs4.existsSync(path5.join(dir, "package.json"))
|
|
1286
|
+
);
|
|
1287
|
+
if (packageRoot) return packageRoot;
|
|
1288
|
+
const inspectoRoot = findNearestAncestorWith(
|
|
1289
|
+
cwd,
|
|
1290
|
+
(dir) => fs4.existsSync(path5.join(dir, ".inspecto"))
|
|
1291
|
+
);
|
|
1292
|
+
if (inspectoRoot) return inspectoRoot;
|
|
1293
|
+
return resolveGitRoot(cwd) ?? cwd;
|
|
1180
1294
|
}
|
|
1181
1295
|
|
|
1182
1296
|
// src/server/server-url.ts
|
|
1183
1297
|
function resolveServerHost(cwd, configRoot) {
|
|
1298
|
+
if (process.env["VITEST"]) return "127.0.0.1";
|
|
1184
1299
|
const userConfig = loadUserConfigSync(false, cwd, configRoot);
|
|
1185
1300
|
const configuredHost = userConfig["server.host"]?.trim();
|
|
1186
1301
|
if (configuredHost) return configuredHost;
|
|
1187
|
-
if (process.env["VITEST"]) return "127.0.0.1";
|
|
1188
1302
|
return "127.0.0.1";
|
|
1189
1303
|
}
|
|
1190
1304
|
|
|
@@ -1240,7 +1354,7 @@ async function startServer() {
|
|
|
1240
1354
|
return serverState.port;
|
|
1241
1355
|
}
|
|
1242
1356
|
serverState.projectRoot = resolveProjectRoot();
|
|
1243
|
-
serverState.configRoot =
|
|
1357
|
+
serverState.configRoot = resolveWorkspaceRoot();
|
|
1244
1358
|
serverState.cwd = process.cwd();
|
|
1245
1359
|
const serverHost = resolveServerHost(serverState.cwd, serverState.configRoot);
|
|
1246
1360
|
portfinder.basePort = 5678;
|
|
@@ -1653,10 +1767,23 @@ data: ${JSON.stringify({ ok: true })}
|
|
|
1653
1767
|
}
|
|
1654
1768
|
async function dispatchToAi(req) {
|
|
1655
1769
|
const { location, snippet, prompt } = req;
|
|
1656
|
-
|
|
1770
|
+
if (prompt?.trim()) {
|
|
1771
|
+
const runtime2 = resolvePromptDispatchRuntime(serverState);
|
|
1772
|
+
return dispatchPromptThroughIde(runtime2, {
|
|
1773
|
+
prompt: prompt.trim()
|
|
1774
|
+
});
|
|
1775
|
+
}
|
|
1776
|
+
if (!location) {
|
|
1777
|
+
return {
|
|
1778
|
+
success: false,
|
|
1779
|
+
error: "Source location is required when prompt is omitted.",
|
|
1780
|
+
errorCode: "INVALID_REQUEST"
|
|
1781
|
+
};
|
|
1782
|
+
}
|
|
1783
|
+
const formattedPrompt = `Please help me with this code from \`${location.file}\` (line ${location.line}):
|
|
1657
1784
|
|
|
1658
1785
|
\`\`\`
|
|
1659
|
-
${snippet}
|
|
1786
|
+
${snippet ?? ""}
|
|
1660
1787
|
\`\`\`
|
|
1661
1788
|
`;
|
|
1662
1789
|
const runtime = resolvePromptDispatchRuntime(serverState);
|
|
@@ -1665,7 +1792,7 @@ ${snippet}
|
|
|
1665
1792
|
filePath: location.file,
|
|
1666
1793
|
line: location.line,
|
|
1667
1794
|
column: location.column,
|
|
1668
|
-
snippet
|
|
1795
|
+
...snippet !== void 0 ? { snippet } : {}
|
|
1669
1796
|
});
|
|
1670
1797
|
}
|
|
1671
1798
|
function getBatchDispatchStatusCode(errorCode, success) {
|