@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
package/dist/astro.js
CHANGED
|
@@ -130,7 +130,8 @@ import { createDefu } from "defu";
|
|
|
130
130
|
import {
|
|
131
131
|
DEFAULT_PROVIDER_MODE,
|
|
132
132
|
VALID_MODES,
|
|
133
|
-
DEFAULT_INTENTS
|
|
133
|
+
DEFAULT_INTENTS,
|
|
134
|
+
isWorkflowConfig
|
|
134
135
|
} from "@inspecto-dev/types";
|
|
135
136
|
|
|
136
137
|
// src/utils/logger.ts
|
|
@@ -378,13 +379,28 @@ function resolveIntents(serverPrompts) {
|
|
|
378
379
|
);
|
|
379
380
|
continue;
|
|
380
381
|
}
|
|
381
|
-
if (
|
|
382
|
-
|
|
383
|
-
|
|
382
|
+
if (item.kind === "workflow") {
|
|
383
|
+
if (!item.prompt) {
|
|
384
|
+
configLogger.warn(`Workflow "${item.id}" missing required "prompt", skipping`);
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
result.push({
|
|
388
|
+
kind: "workflow",
|
|
389
|
+
id: item.id,
|
|
390
|
+
label: item.label ?? item.id,
|
|
391
|
+
prompt: item.prompt,
|
|
392
|
+
confirm: item.confirm ?? false,
|
|
393
|
+
enabled: item.enabled ?? true
|
|
394
|
+
});
|
|
395
|
+
} else {
|
|
396
|
+
if (!item.aiIntent) {
|
|
397
|
+
configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
result.push(
|
|
401
|
+
baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item
|
|
402
|
+
);
|
|
384
403
|
}
|
|
385
|
-
result.push(
|
|
386
|
-
baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item
|
|
387
|
-
);
|
|
388
404
|
}
|
|
389
405
|
}
|
|
390
406
|
return result;
|
|
@@ -404,26 +420,61 @@ function resolveIntents(serverPrompts) {
|
|
|
404
420
|
configLogger.warn('Intent object missing required "id" field, skipping.');
|
|
405
421
|
continue;
|
|
406
422
|
}
|
|
407
|
-
if (
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
423
|
+
if (item.kind === "workflow") {
|
|
424
|
+
if (!item.prompt) {
|
|
425
|
+
configLogger.warn(`Workflow "${item.id}" missing required "prompt", skipping`);
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
const wfConfig = {
|
|
429
|
+
kind: "workflow",
|
|
430
|
+
id: item.id,
|
|
431
|
+
label: item.label ?? item.id,
|
|
432
|
+
prompt: item.prompt,
|
|
433
|
+
confirm: item.confirm ?? false,
|
|
434
|
+
enabled: item.enabled ?? true
|
|
435
|
+
};
|
|
436
|
+
const existingIdx = merged.findIndex((i2) => i2.id === item.id);
|
|
437
|
+
if (existingIdx !== -1) {
|
|
438
|
+
if (item.enabled === false) {
|
|
439
|
+
merged.splice(existingIdx, 1);
|
|
440
|
+
} else {
|
|
441
|
+
merged[existingIdx] = wfConfig;
|
|
442
|
+
}
|
|
415
443
|
} else {
|
|
416
|
-
|
|
444
|
+
if (item.enabled !== false) {
|
|
445
|
+
merged.push(wfConfig);
|
|
446
|
+
}
|
|
417
447
|
}
|
|
418
448
|
} else {
|
|
419
|
-
if (item.
|
|
420
|
-
|
|
449
|
+
if (!item.aiIntent) {
|
|
450
|
+
configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
const existingIdx = merged.findIndex((i2) => i2.id === item.id);
|
|
454
|
+
if (existingIdx !== -1) {
|
|
455
|
+
if (item.enabled === false) {
|
|
456
|
+
merged.splice(existingIdx, 1);
|
|
457
|
+
} else {
|
|
458
|
+
merged[existingIdx] = { ...merged[existingIdx], ...item };
|
|
459
|
+
}
|
|
460
|
+
} else {
|
|
461
|
+
if (item.enabled !== false) {
|
|
462
|
+
merged.push(item);
|
|
463
|
+
}
|
|
421
464
|
}
|
|
422
465
|
}
|
|
423
466
|
}
|
|
424
467
|
}
|
|
425
468
|
return merged;
|
|
426
469
|
}
|
|
470
|
+
function resolveWorkflowSlots(intents) {
|
|
471
|
+
return intents.filter(isWorkflowConfig).filter((w3) => w3.enabled !== false).map((w3) => ({
|
|
472
|
+
id: w3.id,
|
|
473
|
+
label: w3.label ?? w3.id,
|
|
474
|
+
prompt: w3.prompt,
|
|
475
|
+
confirm: w3.confirm ?? false
|
|
476
|
+
}));
|
|
477
|
+
}
|
|
427
478
|
var watchers = [];
|
|
428
479
|
function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
|
|
429
480
|
if (isWatching) return;
|
|
@@ -653,6 +704,10 @@ function assertPathWithinIdeOpenScope(file, projectRoot) {
|
|
|
653
704
|
}
|
|
654
705
|
}
|
|
655
706
|
|
|
707
|
+
// src/server/annotation-dispatch.ts
|
|
708
|
+
import { exec } from "child_process";
|
|
709
|
+
import { promisify } from "util";
|
|
710
|
+
|
|
656
711
|
// src/server/session-store.ts
|
|
657
712
|
var DEFAULT_STATUS = "pending";
|
|
658
713
|
function createAnnotationSessionStore(options = {}) {
|
|
@@ -660,8 +715,12 @@ function createAnnotationSessionStore(options = {}) {
|
|
|
660
715
|
const listeners = /* @__PURE__ */ new Set();
|
|
661
716
|
const now = options.now ?? (() => Date.now());
|
|
662
717
|
const createId = options.createId ?? createRandomId;
|
|
663
|
-
function findNewestMatchingSession(statuses) {
|
|
664
|
-
return [...sessions.values()].filter((session) =>
|
|
718
|
+
function findNewestMatchingSession(statuses, source) {
|
|
719
|
+
return [...sessions.values()].filter((session) => {
|
|
720
|
+
if (statuses && !statuses.has(session.status)) return false;
|
|
721
|
+
if (source && session.source !== source) return false;
|
|
722
|
+
return true;
|
|
723
|
+
}).sort((left, right) => right.updatedAt - left.updatedAt)[0] ?? null;
|
|
665
724
|
}
|
|
666
725
|
function updateSessionStatus(id, status) {
|
|
667
726
|
const session = sessions.get(id);
|
|
@@ -721,7 +780,7 @@ function createAnnotationSessionStore(options = {}) {
|
|
|
721
780
|
},
|
|
722
781
|
async claimNextSession(options2 = {}) {
|
|
723
782
|
const statuses = normalizeStatuses(DEFAULT_STATUS);
|
|
724
|
-
const existingSession = findNewestMatchingSession(statuses);
|
|
783
|
+
const existingSession = findNewestMatchingSession(statuses, options2.source);
|
|
725
784
|
if (existingSession) {
|
|
726
785
|
return {
|
|
727
786
|
session: claimSession(existingSession.id, statuses),
|
|
@@ -836,6 +895,7 @@ function cloneValue(value) {
|
|
|
836
895
|
}
|
|
837
896
|
|
|
838
897
|
// src/server/annotation-dispatch.ts
|
|
898
|
+
var execAsync = promisify(exec);
|
|
839
899
|
var AnnotationDispatchError = class extends Error {
|
|
840
900
|
constructor(message, errorCode) {
|
|
841
901
|
super(message);
|
|
@@ -847,9 +907,14 @@ async function dispatchAnnotationsToAi(req, state, store = annotationSessionStor
|
|
|
847
907
|
try {
|
|
848
908
|
validateAnnotationDispatchRequest(req, state);
|
|
849
909
|
const batch = normalizeAnnotationBatch(req);
|
|
850
|
-
|
|
910
|
+
let prompt = buildAnnotationBatchPrompt(batch);
|
|
911
|
+
if (req.source === "workflow") {
|
|
912
|
+
prompt = await appendProjectMetadata(prompt, state);
|
|
913
|
+
}
|
|
851
914
|
const deliveryMode = normalizeDeliveryMode(req.deliveryMode);
|
|
852
915
|
const session = store.createSession({
|
|
916
|
+
source: req.source || "annotation",
|
|
917
|
+
...req.workflowId ? { workflowId: req.workflowId } : {},
|
|
853
918
|
instruction: batch.instruction,
|
|
854
919
|
annotations: toSessionAnnotations(batch.annotations),
|
|
855
920
|
deliveryMode,
|
|
@@ -875,6 +940,33 @@ async function dispatchAnnotationsToAi(req, state, store = annotationSessionStor
|
|
|
875
940
|
};
|
|
876
941
|
}
|
|
877
942
|
}
|
|
943
|
+
async function appendProjectMetadata(prompt, state) {
|
|
944
|
+
const lines = ["\n## Project"];
|
|
945
|
+
lines.push(`- Root: ${state.projectRoot}`);
|
|
946
|
+
try {
|
|
947
|
+
const options = {
|
|
948
|
+
cwd: state.projectRoot,
|
|
949
|
+
encoding: "utf-8",
|
|
950
|
+
timeout: 2e3
|
|
951
|
+
};
|
|
952
|
+
const { stdout: branchStdout } = await execAsync("git branch --show-current", options);
|
|
953
|
+
const branch = branchStdout.trim();
|
|
954
|
+
lines.push(`- Branch: ${branch}`);
|
|
955
|
+
const { stdout: statusStdout } = await execAsync("git status --porcelain", options);
|
|
956
|
+
const statusRaw = statusStdout.trim();
|
|
957
|
+
const entries = statusRaw ? statusRaw.split("\n") : [];
|
|
958
|
+
const staged = entries.filter((l) => l[0] !== " " && l[0] !== "?").length;
|
|
959
|
+
const unstaged = entries.filter((l) => l[1] !== " " && l[1] !== "?").length;
|
|
960
|
+
const untracked = entries.filter((l) => l[0] === "?").length;
|
|
961
|
+
lines.push(`- Status: ${staged} staged, ${unstaged} unstaged, ${untracked} untracked`);
|
|
962
|
+
} catch (err) {
|
|
963
|
+
console.warn("[inspecto] Failed to get git status for workflow:", err);
|
|
964
|
+
lines.push("- Git: unavailable or check timeout");
|
|
965
|
+
}
|
|
966
|
+
return `${prompt}
|
|
967
|
+
|
|
968
|
+
${lines.join("\n")}`;
|
|
969
|
+
}
|
|
878
970
|
function normalizeDeliveryMode(input) {
|
|
879
971
|
return input === "agent" ? "agent" : "ide";
|
|
880
972
|
}
|
|
@@ -911,7 +1003,7 @@ function toSessionSummary(session) {
|
|
|
911
1003
|
};
|
|
912
1004
|
}
|
|
913
1005
|
function validateAnnotationDispatchRequest(req, state) {
|
|
914
|
-
if (!req.annotations.length) {
|
|
1006
|
+
if (!req.annotations.length && req.source !== "workflow") {
|
|
915
1007
|
throw new AnnotationDispatchError("At least one annotation is required.", "INVALID_REQUEST");
|
|
916
1008
|
}
|
|
917
1009
|
for (const annotation of req.annotations) {
|
|
@@ -1013,6 +1105,7 @@ function getAnnotationDispatchErrorCode(error) {
|
|
|
1013
1105
|
}
|
|
1014
1106
|
|
|
1015
1107
|
// src/server/client-config.ts
|
|
1108
|
+
import { isAiIntentConfig } from "@inspecto-dev/types";
|
|
1016
1109
|
async function buildClientConfig(serverState2) {
|
|
1017
1110
|
const userConfig = loadUserConfigSync(false, serverState2.cwd, serverState2.configRoot);
|
|
1018
1111
|
const promptsConfig = await loadPromptsConfig(false, serverState2.cwd, serverState2.configRoot);
|
|
@@ -1024,11 +1117,13 @@ async function buildClientConfig(serverState2) {
|
|
|
1024
1117
|
const { scheme: _scheme, ...rest } = serverState2.ideInfo;
|
|
1025
1118
|
info = rest;
|
|
1026
1119
|
}
|
|
1120
|
+
const allIntents = resolveIntents(promptsConfig);
|
|
1027
1121
|
return {
|
|
1028
1122
|
...info,
|
|
1029
|
-
prompts:
|
|
1123
|
+
prompts: allIntents.filter(isAiIntentConfig),
|
|
1124
|
+
workflows: resolveWorkflowSlots(allIntents),
|
|
1030
1125
|
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
1031
|
-
annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "
|
|
1126
|
+
annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "agent",
|
|
1032
1127
|
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
1033
1128
|
runtimeContext: {
|
|
1034
1129
|
enabled: true,
|
|
@@ -1125,41 +1220,60 @@ import fs4 from "fs";
|
|
|
1125
1220
|
import path4 from "path";
|
|
1126
1221
|
import { execSync } from "child_process";
|
|
1127
1222
|
var serverLogger3 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
1128
|
-
function
|
|
1129
|
-
const cwd = process.cwd();
|
|
1130
|
-
let gitRoot;
|
|
1223
|
+
function resolveGitRoot(_cwd) {
|
|
1131
1224
|
try {
|
|
1132
|
-
|
|
1225
|
+
const output = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" });
|
|
1226
|
+
return typeof output === "string" ? output.trim() : null;
|
|
1133
1227
|
} catch (e) {
|
|
1134
1228
|
serverLogger3.warn("Failed to resolve git root via git rev-parse:", e);
|
|
1135
|
-
gitRoot = cwd;
|
|
1136
|
-
}
|
|
1137
|
-
const visited = /* @__PURE__ */ new Set();
|
|
1138
|
-
const search = (start, stop) => {
|
|
1139
|
-
let current = start;
|
|
1140
|
-
while (!visited.has(current)) {
|
|
1141
|
-
visited.add(current);
|
|
1142
|
-
if (fs4.existsSync(path4.join(current, ".inspecto"))) return current;
|
|
1143
|
-
if (current === stop) break;
|
|
1144
|
-
const parent = path4.dirname(current);
|
|
1145
|
-
if (parent === current) break;
|
|
1146
|
-
current = parent;
|
|
1147
|
-
}
|
|
1148
1229
|
return null;
|
|
1149
|
-
}
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
function findNearestAncestorWith(start, predicate) {
|
|
1233
|
+
let current = start;
|
|
1234
|
+
while (true) {
|
|
1235
|
+
if (predicate(current)) return current;
|
|
1236
|
+
const parent = path4.dirname(current);
|
|
1237
|
+
if (parent === current) break;
|
|
1238
|
+
current = parent;
|
|
1239
|
+
}
|
|
1240
|
+
return null;
|
|
1241
|
+
}
|
|
1242
|
+
function resolveWorkspaceRoot() {
|
|
1243
|
+
const cwd = process.cwd();
|
|
1244
|
+
const inspectoRoot = findNearestAncestorWith(
|
|
1245
|
+
cwd,
|
|
1246
|
+
(dir) => fs4.existsSync(path4.join(dir, ".inspecto"))
|
|
1247
|
+
);
|
|
1248
|
+
if (inspectoRoot) return inspectoRoot;
|
|
1249
|
+
const packageRoot = findNearestAncestorWith(
|
|
1250
|
+
cwd,
|
|
1251
|
+
(dir) => fs4.existsSync(path4.join(dir, "package.json"))
|
|
1252
|
+
);
|
|
1253
|
+
if (packageRoot) return packageRoot;
|
|
1254
|
+
return resolveGitRoot(cwd) ?? cwd;
|
|
1255
|
+
}
|
|
1256
|
+
function resolveProjectRoot() {
|
|
1257
|
+
const cwd = process.cwd();
|
|
1258
|
+
const packageRoot = findNearestAncestorWith(
|
|
1259
|
+
cwd,
|
|
1260
|
+
(dir) => fs4.existsSync(path4.join(dir, "package.json"))
|
|
1261
|
+
);
|
|
1262
|
+
if (packageRoot) return packageRoot;
|
|
1263
|
+
const inspectoRoot = findNearestAncestorWith(
|
|
1264
|
+
cwd,
|
|
1265
|
+
(dir) => fs4.existsSync(path4.join(dir, ".inspecto"))
|
|
1266
|
+
);
|
|
1267
|
+
if (inspectoRoot) return inspectoRoot;
|
|
1268
|
+
return resolveGitRoot(cwd) ?? cwd;
|
|
1155
1269
|
}
|
|
1156
1270
|
|
|
1157
1271
|
// src/server/server-url.ts
|
|
1158
1272
|
function resolveServerHost(cwd, configRoot) {
|
|
1273
|
+
if (process.env["VITEST"]) return "127.0.0.1";
|
|
1159
1274
|
const userConfig = loadUserConfigSync(false, cwd, configRoot);
|
|
1160
1275
|
const configuredHost = userConfig["server.host"]?.trim();
|
|
1161
1276
|
if (configuredHost) return configuredHost;
|
|
1162
|
-
if (process.env["VITEST"]) return "127.0.0.1";
|
|
1163
1277
|
return "127.0.0.1";
|
|
1164
1278
|
}
|
|
1165
1279
|
function resolvePublicServerUrl(args) {
|
|
@@ -1224,7 +1338,7 @@ async function startServer() {
|
|
|
1224
1338
|
return serverState.port;
|
|
1225
1339
|
}
|
|
1226
1340
|
serverState.projectRoot = resolveProjectRoot();
|
|
1227
|
-
serverState.configRoot =
|
|
1341
|
+
serverState.configRoot = resolveWorkspaceRoot();
|
|
1228
1342
|
serverState.cwd = process.cwd();
|
|
1229
1343
|
const serverHost = resolveServerHost(serverState.cwd, serverState.configRoot);
|
|
1230
1344
|
portfinder.basePort = 5678;
|
|
@@ -1637,10 +1751,23 @@ data: ${JSON.stringify({ ok: true })}
|
|
|
1637
1751
|
}
|
|
1638
1752
|
async function dispatchToAi(req) {
|
|
1639
1753
|
const { location, snippet, prompt } = req;
|
|
1640
|
-
|
|
1754
|
+
if (prompt?.trim()) {
|
|
1755
|
+
const runtime2 = resolvePromptDispatchRuntime(serverState);
|
|
1756
|
+
return dispatchPromptThroughIde(runtime2, {
|
|
1757
|
+
prompt: prompt.trim()
|
|
1758
|
+
});
|
|
1759
|
+
}
|
|
1760
|
+
if (!location) {
|
|
1761
|
+
return {
|
|
1762
|
+
success: false,
|
|
1763
|
+
error: "Source location is required when prompt is omitted.",
|
|
1764
|
+
errorCode: "INVALID_REQUEST"
|
|
1765
|
+
};
|
|
1766
|
+
}
|
|
1767
|
+
const formattedPrompt = `Please help me with this code from \`${location.file}\` (line ${location.line}):
|
|
1641
1768
|
|
|
1642
1769
|
\`\`\`
|
|
1643
|
-
${snippet}
|
|
1770
|
+
${snippet ?? ""}
|
|
1644
1771
|
\`\`\`
|
|
1645
1772
|
`;
|
|
1646
1773
|
const runtime = resolvePromptDispatchRuntime(serverState);
|
|
@@ -1649,7 +1776,7 @@ ${snippet}
|
|
|
1649
1776
|
filePath: location.file,
|
|
1650
1777
|
line: location.line,
|
|
1651
1778
|
column: location.column,
|
|
1652
|
-
snippet
|
|
1779
|
+
...snippet !== void 0 ? { snippet } : {}
|
|
1653
1780
|
});
|
|
1654
1781
|
}
|
|
1655
1782
|
function getBatchDispatchStatusCode(errorCode, success) {
|