@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
|
@@ -137,7 +137,8 @@ import { createDefu } from "defu";
|
|
|
137
137
|
import {
|
|
138
138
|
DEFAULT_PROVIDER_MODE,
|
|
139
139
|
VALID_MODES,
|
|
140
|
-
DEFAULT_INTENTS
|
|
140
|
+
DEFAULT_INTENTS,
|
|
141
|
+
isWorkflowConfig
|
|
141
142
|
} from "@inspecto-dev/types";
|
|
142
143
|
|
|
143
144
|
// src/utils/logger.ts
|
|
@@ -371,13 +372,28 @@ function resolveIntents(serverPrompts) {
|
|
|
371
372
|
);
|
|
372
373
|
continue;
|
|
373
374
|
}
|
|
374
|
-
if (
|
|
375
|
-
|
|
376
|
-
|
|
375
|
+
if (item.kind === "workflow") {
|
|
376
|
+
if (!item.prompt) {
|
|
377
|
+
configLogger.warn(`Workflow "${item.id}" missing required "prompt", skipping`);
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
result.push({
|
|
381
|
+
kind: "workflow",
|
|
382
|
+
id: item.id,
|
|
383
|
+
label: item.label ?? item.id,
|
|
384
|
+
prompt: item.prompt,
|
|
385
|
+
confirm: item.confirm ?? false,
|
|
386
|
+
enabled: item.enabled ?? true
|
|
387
|
+
});
|
|
388
|
+
} else {
|
|
389
|
+
if (!item.aiIntent) {
|
|
390
|
+
configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
result.push(
|
|
394
|
+
baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item
|
|
395
|
+
);
|
|
377
396
|
}
|
|
378
|
-
result.push(
|
|
379
|
-
baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item
|
|
380
|
-
);
|
|
381
397
|
}
|
|
382
398
|
}
|
|
383
399
|
return result;
|
|
@@ -397,26 +413,61 @@ function resolveIntents(serverPrompts) {
|
|
|
397
413
|
configLogger.warn('Intent object missing required "id" field, skipping.');
|
|
398
414
|
continue;
|
|
399
415
|
}
|
|
400
|
-
if (
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
416
|
+
if (item.kind === "workflow") {
|
|
417
|
+
if (!item.prompt) {
|
|
418
|
+
configLogger.warn(`Workflow "${item.id}" missing required "prompt", skipping`);
|
|
419
|
+
continue;
|
|
420
|
+
}
|
|
421
|
+
const wfConfig = {
|
|
422
|
+
kind: "workflow",
|
|
423
|
+
id: item.id,
|
|
424
|
+
label: item.label ?? item.id,
|
|
425
|
+
prompt: item.prompt,
|
|
426
|
+
confirm: item.confirm ?? false,
|
|
427
|
+
enabled: item.enabled ?? true
|
|
428
|
+
};
|
|
429
|
+
const existingIdx = merged.findIndex((i) => i.id === item.id);
|
|
430
|
+
if (existingIdx !== -1) {
|
|
431
|
+
if (item.enabled === false) {
|
|
432
|
+
merged.splice(existingIdx, 1);
|
|
433
|
+
} else {
|
|
434
|
+
merged[existingIdx] = wfConfig;
|
|
435
|
+
}
|
|
408
436
|
} else {
|
|
409
|
-
|
|
437
|
+
if (item.enabled !== false) {
|
|
438
|
+
merged.push(wfConfig);
|
|
439
|
+
}
|
|
410
440
|
}
|
|
411
441
|
} else {
|
|
412
|
-
if (item.
|
|
413
|
-
|
|
442
|
+
if (!item.aiIntent) {
|
|
443
|
+
configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
const existingIdx = merged.findIndex((i) => i.id === item.id);
|
|
447
|
+
if (existingIdx !== -1) {
|
|
448
|
+
if (item.enabled === false) {
|
|
449
|
+
merged.splice(existingIdx, 1);
|
|
450
|
+
} else {
|
|
451
|
+
merged[existingIdx] = { ...merged[existingIdx], ...item };
|
|
452
|
+
}
|
|
453
|
+
} else {
|
|
454
|
+
if (item.enabled !== false) {
|
|
455
|
+
merged.push(item);
|
|
456
|
+
}
|
|
414
457
|
}
|
|
415
458
|
}
|
|
416
459
|
}
|
|
417
460
|
}
|
|
418
461
|
return merged;
|
|
419
462
|
}
|
|
463
|
+
function resolveWorkflowSlots(intents) {
|
|
464
|
+
return intents.filter(isWorkflowConfig).filter((w) => w.enabled !== false).map((w) => ({
|
|
465
|
+
id: w.id,
|
|
466
|
+
label: w.label ?? w.id,
|
|
467
|
+
prompt: w.prompt,
|
|
468
|
+
confirm: w.confirm ?? false
|
|
469
|
+
}));
|
|
470
|
+
}
|
|
420
471
|
var watchers = [];
|
|
421
472
|
function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
|
|
422
473
|
if (isWatching) return;
|
|
@@ -646,6 +697,10 @@ function assertPathWithinIdeOpenScope(file, projectRoot) {
|
|
|
646
697
|
}
|
|
647
698
|
}
|
|
648
699
|
|
|
700
|
+
// src/server/annotation-dispatch.ts
|
|
701
|
+
import { exec } from "child_process";
|
|
702
|
+
import { promisify } from "util";
|
|
703
|
+
|
|
649
704
|
// src/server/session-store.ts
|
|
650
705
|
var DEFAULT_STATUS = "pending";
|
|
651
706
|
function createAnnotationSessionStore(options = {}) {
|
|
@@ -653,8 +708,12 @@ function createAnnotationSessionStore(options = {}) {
|
|
|
653
708
|
const listeners = /* @__PURE__ */ new Set();
|
|
654
709
|
const now = options.now ?? (() => Date.now());
|
|
655
710
|
const createId = options.createId ?? createRandomId;
|
|
656
|
-
function findNewestMatchingSession(statuses) {
|
|
657
|
-
return [...sessions.values()].filter((session) =>
|
|
711
|
+
function findNewestMatchingSession(statuses, source) {
|
|
712
|
+
return [...sessions.values()].filter((session) => {
|
|
713
|
+
if (statuses && !statuses.has(session.status)) return false;
|
|
714
|
+
if (source && session.source !== source) return false;
|
|
715
|
+
return true;
|
|
716
|
+
}).sort((left, right) => right.updatedAt - left.updatedAt)[0] ?? null;
|
|
658
717
|
}
|
|
659
718
|
function updateSessionStatus(id, status) {
|
|
660
719
|
const session = sessions.get(id);
|
|
@@ -714,7 +773,7 @@ function createAnnotationSessionStore(options = {}) {
|
|
|
714
773
|
},
|
|
715
774
|
async claimNextSession(options2 = {}) {
|
|
716
775
|
const statuses = normalizeStatuses(DEFAULT_STATUS);
|
|
717
|
-
const existingSession = findNewestMatchingSession(statuses);
|
|
776
|
+
const existingSession = findNewestMatchingSession(statuses, options2.source);
|
|
718
777
|
if (existingSession) {
|
|
719
778
|
return {
|
|
720
779
|
session: claimSession(existingSession.id, statuses),
|
|
@@ -829,6 +888,7 @@ function cloneValue(value) {
|
|
|
829
888
|
}
|
|
830
889
|
|
|
831
890
|
// src/server/annotation-dispatch.ts
|
|
891
|
+
var execAsync = promisify(exec);
|
|
832
892
|
var AnnotationDispatchError = class extends Error {
|
|
833
893
|
constructor(message, errorCode) {
|
|
834
894
|
super(message);
|
|
@@ -840,9 +900,14 @@ async function dispatchAnnotationsToAi(req, state, store = annotationSessionStor
|
|
|
840
900
|
try {
|
|
841
901
|
validateAnnotationDispatchRequest(req, state);
|
|
842
902
|
const batch = normalizeAnnotationBatch(req);
|
|
843
|
-
|
|
903
|
+
let prompt = buildAnnotationBatchPrompt(batch);
|
|
904
|
+
if (req.source === "workflow") {
|
|
905
|
+
prompt = await appendProjectMetadata(prompt, state);
|
|
906
|
+
}
|
|
844
907
|
const deliveryMode = normalizeDeliveryMode(req.deliveryMode);
|
|
845
908
|
const session = store.createSession({
|
|
909
|
+
source: req.source || "annotation",
|
|
910
|
+
...req.workflowId ? { workflowId: req.workflowId } : {},
|
|
846
911
|
instruction: batch.instruction,
|
|
847
912
|
annotations: toSessionAnnotations(batch.annotations),
|
|
848
913
|
deliveryMode,
|
|
@@ -868,6 +933,33 @@ async function dispatchAnnotationsToAi(req, state, store = annotationSessionStor
|
|
|
868
933
|
};
|
|
869
934
|
}
|
|
870
935
|
}
|
|
936
|
+
async function appendProjectMetadata(prompt, state) {
|
|
937
|
+
const lines = ["\n## Project"];
|
|
938
|
+
lines.push(`- Root: ${state.projectRoot}`);
|
|
939
|
+
try {
|
|
940
|
+
const options = {
|
|
941
|
+
cwd: state.projectRoot,
|
|
942
|
+
encoding: "utf-8",
|
|
943
|
+
timeout: 2e3
|
|
944
|
+
};
|
|
945
|
+
const { stdout: branchStdout } = await execAsync("git branch --show-current", options);
|
|
946
|
+
const branch = branchStdout.trim();
|
|
947
|
+
lines.push(`- Branch: ${branch}`);
|
|
948
|
+
const { stdout: statusStdout } = await execAsync("git status --porcelain", options);
|
|
949
|
+
const statusRaw = statusStdout.trim();
|
|
950
|
+
const entries = statusRaw ? statusRaw.split("\n") : [];
|
|
951
|
+
const staged = entries.filter((l) => l[0] !== " " && l[0] !== "?").length;
|
|
952
|
+
const unstaged = entries.filter((l) => l[1] !== " " && l[1] !== "?").length;
|
|
953
|
+
const untracked = entries.filter((l) => l[0] === "?").length;
|
|
954
|
+
lines.push(`- Status: ${staged} staged, ${unstaged} unstaged, ${untracked} untracked`);
|
|
955
|
+
} catch (err) {
|
|
956
|
+
console.warn("[inspecto] Failed to get git status for workflow:", err);
|
|
957
|
+
lines.push("- Git: unavailable or check timeout");
|
|
958
|
+
}
|
|
959
|
+
return `${prompt}
|
|
960
|
+
|
|
961
|
+
${lines.join("\n")}`;
|
|
962
|
+
}
|
|
871
963
|
function normalizeDeliveryMode(input) {
|
|
872
964
|
return input === "agent" ? "agent" : "ide";
|
|
873
965
|
}
|
|
@@ -904,7 +996,7 @@ function toSessionSummary(session) {
|
|
|
904
996
|
};
|
|
905
997
|
}
|
|
906
998
|
function validateAnnotationDispatchRequest(req, state) {
|
|
907
|
-
if (!req.annotations.length) {
|
|
999
|
+
if (!req.annotations.length && req.source !== "workflow") {
|
|
908
1000
|
throw new AnnotationDispatchError("At least one annotation is required.", "INVALID_REQUEST");
|
|
909
1001
|
}
|
|
910
1002
|
for (const annotation of req.annotations) {
|
|
@@ -1006,6 +1098,7 @@ function getAnnotationDispatchErrorCode(error) {
|
|
|
1006
1098
|
}
|
|
1007
1099
|
|
|
1008
1100
|
// src/server/client-config.ts
|
|
1101
|
+
import { isAiIntentConfig } from "@inspecto-dev/types";
|
|
1009
1102
|
async function buildClientConfig(serverState2) {
|
|
1010
1103
|
const userConfig = loadUserConfigSync(false, serverState2.cwd, serverState2.configRoot);
|
|
1011
1104
|
const promptsConfig = await loadPromptsConfig(false, serverState2.cwd, serverState2.configRoot);
|
|
@@ -1017,11 +1110,13 @@ async function buildClientConfig(serverState2) {
|
|
|
1017
1110
|
const { scheme: _scheme, ...rest } = serverState2.ideInfo;
|
|
1018
1111
|
info = rest;
|
|
1019
1112
|
}
|
|
1113
|
+
const allIntents = resolveIntents(promptsConfig);
|
|
1020
1114
|
return {
|
|
1021
1115
|
...info,
|
|
1022
|
-
prompts:
|
|
1116
|
+
prompts: allIntents.filter(isAiIntentConfig),
|
|
1117
|
+
workflows: resolveWorkflowSlots(allIntents),
|
|
1023
1118
|
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
1024
|
-
annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "
|
|
1119
|
+
annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "agent",
|
|
1025
1120
|
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
1026
1121
|
runtimeContext: {
|
|
1027
1122
|
enabled: true,
|
|
@@ -1118,41 +1213,60 @@ import fs4 from "fs";
|
|
|
1118
1213
|
import path5 from "path";
|
|
1119
1214
|
import { execSync } from "child_process";
|
|
1120
1215
|
var serverLogger3 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
1121
|
-
function
|
|
1122
|
-
const cwd = process.cwd();
|
|
1123
|
-
let gitRoot;
|
|
1216
|
+
function resolveGitRoot(_cwd) {
|
|
1124
1217
|
try {
|
|
1125
|
-
|
|
1218
|
+
const output = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" });
|
|
1219
|
+
return typeof output === "string" ? output.trim() : null;
|
|
1126
1220
|
} catch (e) {
|
|
1127
1221
|
serverLogger3.warn("Failed to resolve git root via git rev-parse:", e);
|
|
1128
|
-
gitRoot = cwd;
|
|
1129
|
-
}
|
|
1130
|
-
const visited = /* @__PURE__ */ new Set();
|
|
1131
|
-
const search = (start, stop) => {
|
|
1132
|
-
let current = start;
|
|
1133
|
-
while (!visited.has(current)) {
|
|
1134
|
-
visited.add(current);
|
|
1135
|
-
if (fs4.existsSync(path5.join(current, ".inspecto"))) return current;
|
|
1136
|
-
if (current === stop) break;
|
|
1137
|
-
const parent = path5.dirname(current);
|
|
1138
|
-
if (parent === current) break;
|
|
1139
|
-
current = parent;
|
|
1140
|
-
}
|
|
1141
1222
|
return null;
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
function findNearestAncestorWith(start, predicate) {
|
|
1226
|
+
let current = start;
|
|
1227
|
+
while (true) {
|
|
1228
|
+
if (predicate(current)) return current;
|
|
1229
|
+
const parent = path5.dirname(current);
|
|
1230
|
+
if (parent === current) break;
|
|
1231
|
+
current = parent;
|
|
1232
|
+
}
|
|
1233
|
+
return null;
|
|
1234
|
+
}
|
|
1235
|
+
function resolveWorkspaceRoot() {
|
|
1236
|
+
const cwd = process.cwd();
|
|
1237
|
+
const inspectoRoot = findNearestAncestorWith(
|
|
1238
|
+
cwd,
|
|
1239
|
+
(dir) => fs4.existsSync(path5.join(dir, ".inspecto"))
|
|
1240
|
+
);
|
|
1241
|
+
if (inspectoRoot) return inspectoRoot;
|
|
1242
|
+
const packageRoot = findNearestAncestorWith(
|
|
1243
|
+
cwd,
|
|
1244
|
+
(dir) => fs4.existsSync(path5.join(dir, "package.json"))
|
|
1245
|
+
);
|
|
1246
|
+
if (packageRoot) return packageRoot;
|
|
1247
|
+
return resolveGitRoot(cwd) ?? cwd;
|
|
1248
|
+
}
|
|
1249
|
+
function resolveProjectRoot() {
|
|
1250
|
+
const cwd = process.cwd();
|
|
1251
|
+
const packageRoot = findNearestAncestorWith(
|
|
1252
|
+
cwd,
|
|
1253
|
+
(dir) => fs4.existsSync(path5.join(dir, "package.json"))
|
|
1254
|
+
);
|
|
1255
|
+
if (packageRoot) return packageRoot;
|
|
1256
|
+
const inspectoRoot = findNearestAncestorWith(
|
|
1257
|
+
cwd,
|
|
1258
|
+
(dir) => fs4.existsSync(path5.join(dir, ".inspecto"))
|
|
1259
|
+
);
|
|
1260
|
+
if (inspectoRoot) return inspectoRoot;
|
|
1261
|
+
return resolveGitRoot(cwd) ?? cwd;
|
|
1148
1262
|
}
|
|
1149
1263
|
|
|
1150
1264
|
// src/server/server-url.ts
|
|
1151
1265
|
function resolveServerHost(cwd, configRoot) {
|
|
1266
|
+
if (process.env["VITEST"]) return "127.0.0.1";
|
|
1152
1267
|
const userConfig = loadUserConfigSync(false, cwd, configRoot);
|
|
1153
1268
|
const configuredHost = userConfig["server.host"]?.trim();
|
|
1154
1269
|
if (configuredHost) return configuredHost;
|
|
1155
|
-
if (process.env["VITEST"]) return "127.0.0.1";
|
|
1156
1270
|
return "127.0.0.1";
|
|
1157
1271
|
}
|
|
1158
1272
|
|
|
@@ -1208,7 +1322,7 @@ async function startServer() {
|
|
|
1208
1322
|
return serverState.port;
|
|
1209
1323
|
}
|
|
1210
1324
|
serverState.projectRoot = resolveProjectRoot();
|
|
1211
|
-
serverState.configRoot =
|
|
1325
|
+
serverState.configRoot = resolveWorkspaceRoot();
|
|
1212
1326
|
serverState.cwd = process.cwd();
|
|
1213
1327
|
const serverHost = resolveServerHost(serverState.cwd, serverState.configRoot);
|
|
1214
1328
|
portfinder.basePort = 5678;
|
|
@@ -1621,10 +1735,23 @@ data: ${JSON.stringify({ ok: true })}
|
|
|
1621
1735
|
}
|
|
1622
1736
|
async function dispatchToAi(req) {
|
|
1623
1737
|
const { location, snippet, prompt } = req;
|
|
1624
|
-
|
|
1738
|
+
if (prompt?.trim()) {
|
|
1739
|
+
const runtime2 = resolvePromptDispatchRuntime(serverState);
|
|
1740
|
+
return dispatchPromptThroughIde(runtime2, {
|
|
1741
|
+
prompt: prompt.trim()
|
|
1742
|
+
});
|
|
1743
|
+
}
|
|
1744
|
+
if (!location) {
|
|
1745
|
+
return {
|
|
1746
|
+
success: false,
|
|
1747
|
+
error: "Source location is required when prompt is omitted.",
|
|
1748
|
+
errorCode: "INVALID_REQUEST"
|
|
1749
|
+
};
|
|
1750
|
+
}
|
|
1751
|
+
const formattedPrompt = `Please help me with this code from \`${location.file}\` (line ${location.line}):
|
|
1625
1752
|
|
|
1626
1753
|
\`\`\`
|
|
1627
|
-
${snippet}
|
|
1754
|
+
${snippet ?? ""}
|
|
1628
1755
|
\`\`\`
|
|
1629
1756
|
`;
|
|
1630
1757
|
const runtime = resolvePromptDispatchRuntime(serverState);
|
|
@@ -1633,7 +1760,7 @@ ${snippet}
|
|
|
1633
1760
|
filePath: location.file,
|
|
1634
1761
|
line: location.line,
|
|
1635
1762
|
column: location.column,
|
|
1636
|
-
snippet
|
|
1763
|
+
...snippet !== void 0 ? { snippet } : {}
|
|
1637
1764
|
});
|
|
1638
1765
|
}
|
|
1639
1766
|
function getBatchDispatchStatusCode(errorCode, success) {
|