@algolia/wizard 0.100.0 → 0.102.0
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/main.js
CHANGED
|
@@ -2447,7 +2447,7 @@ async function ensureApplication(resumeAppId) {
|
|
|
2447
2447
|
// package.json
|
|
2448
2448
|
var package_default = {
|
|
2449
2449
|
name: "@algolia/wizard",
|
|
2450
|
-
version: "0.
|
|
2450
|
+
version: "0.102.0",
|
|
2451
2451
|
description: "Magically implement Algolia functionality in your codebase",
|
|
2452
2452
|
type: "module",
|
|
2453
2453
|
engines: {
|
|
@@ -3075,7 +3075,6 @@ var selectIndexStep = async (ctx) => {
|
|
|
3075
3075
|
// src/lib/agent.ts
|
|
3076
3076
|
import {
|
|
3077
3077
|
ToolLoopAgent,
|
|
3078
|
-
hasToolCall,
|
|
3079
3078
|
Output as Output3,
|
|
3080
3079
|
APICallError,
|
|
3081
3080
|
NoOutputGeneratedError,
|
|
@@ -3167,6 +3166,22 @@ function resolveInRoot(ctx, path) {
|
|
|
3167
3166
|
}
|
|
3168
3167
|
return { ok: true, target };
|
|
3169
3168
|
}
|
|
3169
|
+
function isPackageManifest(parts) {
|
|
3170
|
+
if (parts.at(-1) !== "package.json") return false;
|
|
3171
|
+
return parts.length === 2 || parts.length === 3 && parts[0].startsWith("@");
|
|
3172
|
+
}
|
|
3173
|
+
var DEPENDENCY_INTERNALS_REFUSAL = "Refused: do not explore node_modules. Use the Algolia SDK reference and the type checker output. To check an installed version, read node_modules/<package>/package.json.";
|
|
3174
|
+
function dependencyInternalsRefusal(ctx, target) {
|
|
3175
|
+
if (!ctx.dependencyManifestsOnly) return null;
|
|
3176
|
+
const parts = relative(ctx.root, target).split(sep);
|
|
3177
|
+
const index = parts.lastIndexOf("node_modules");
|
|
3178
|
+
if (index === -1 || isPackageManifest(parts.slice(index + 1))) return null;
|
|
3179
|
+
return DEPENDENCY_INTERNALS_REFUSAL;
|
|
3180
|
+
}
|
|
3181
|
+
var DEPENDENCY_INTERNALS_PATH = /node_modules\/(?!\.bin\/|(?:@[^/\s'"`]+\/)?[^/\s'"`]+\/package\.json\b)/;
|
|
3182
|
+
function commandNamesDependencyInternals(ctx, command) {
|
|
3183
|
+
return Boolean(ctx.dependencyManifestsOnly) && DEPENDENCY_INTERNALS_PATH.test(command);
|
|
3184
|
+
}
|
|
3170
3185
|
async function hasSymlinkParent(ctx, target) {
|
|
3171
3186
|
let current = ctx.root;
|
|
3172
3187
|
const parts = relative(ctx.root, dirname2(target)).split(sep).filter(Boolean);
|
|
@@ -3230,6 +3245,8 @@ function listFilesTool(ctx) {
|
|
|
3230
3245
|
}
|
|
3231
3246
|
const resolved2 = resolveInRoot(ctx, path);
|
|
3232
3247
|
if (!resolved2.ok) return resolved2.error;
|
|
3248
|
+
const refusal = dependencyInternalsRefusal(ctx, resolved2.target);
|
|
3249
|
+
if (refusal) return refusal;
|
|
3233
3250
|
try {
|
|
3234
3251
|
const entries = await readdir(resolved2.target, { withFileTypes: true });
|
|
3235
3252
|
return entries.map((e) => e.isDirectory() ? `${e.name}/` : e.name).join("\n");
|
|
@@ -3271,6 +3288,19 @@ function changeDirectoryTool(ctx) {
|
|
|
3271
3288
|
// src/lib/tools/reportStatus.ts
|
|
3272
3289
|
import { tool as tool3 } from "ai";
|
|
3273
3290
|
import z8 from "zod";
|
|
3291
|
+
var PLACEHOLDER_REPORT_REFUSAL = 'Refused: reportStatus got the placeholder text "placeholder" instead of a real result. The task is not finished. Continue the task, then call reportStatus with the real status, reason, and output.';
|
|
3292
|
+
var PLACEHOLDER_VALUE = /^\s*placeholder\s*$/i;
|
|
3293
|
+
function isPlaceholder(value) {
|
|
3294
|
+
return typeof value === "string" && PLACEHOLDER_VALUE.test(value);
|
|
3295
|
+
}
|
|
3296
|
+
function hasPlaceholder(reason, output) {
|
|
3297
|
+
if (isPlaceholder(reason)) return true;
|
|
3298
|
+
if (typeof output !== "object" || output === null) return false;
|
|
3299
|
+
return Object.values(output).some(isPlaceholder);
|
|
3300
|
+
}
|
|
3301
|
+
function isAcceptedReport(result) {
|
|
3302
|
+
return typeof result === "object" && result !== null && "status" in result && !("rejected" in result);
|
|
3303
|
+
}
|
|
3274
3304
|
function reportStatusTool(output) {
|
|
3275
3305
|
return tool3({
|
|
3276
3306
|
description: "Report the status of your execution. Return a reason in case of failure.",
|
|
@@ -3280,6 +3310,10 @@ function reportStatusTool(output) {
|
|
|
3280
3310
|
output
|
|
3281
3311
|
}),
|
|
3282
3312
|
execute: async ({ status, reason, output: output2 }) => {
|
|
3313
|
+
if (hasPlaceholder(reason, output2)) {
|
|
3314
|
+
logger.warn({ status, reason }, "reportStatus: refused a placeholder report");
|
|
3315
|
+
return { rejected: true, message: PLACEHOLDER_REPORT_REFUSAL };
|
|
3316
|
+
}
|
|
3283
3317
|
logger.info({ status, reason }, "called reportStatus tool");
|
|
3284
3318
|
return { status, reason, output: output2 };
|
|
3285
3319
|
}
|
|
@@ -3379,6 +3413,8 @@ function readFileTool(ctx) {
|
|
|
3379
3413
|
logger.info({ filePath, readLines }, "called readFile tool");
|
|
3380
3414
|
const resolved2 = resolveInRoot(ctx, filePath);
|
|
3381
3415
|
if (resolved2.ok === false) return resolved2.error;
|
|
3416
|
+
const refusal = dependencyInternalsRefusal(ctx, resolved2.target);
|
|
3417
|
+
if (refusal) return refusal;
|
|
3382
3418
|
try {
|
|
3383
3419
|
const content = await readFile4(resolved2.target, "utf8");
|
|
3384
3420
|
const safeContent = isEnvFile(resolved2.target) ? redactEnvValues(content) : content;
|
|
@@ -4323,6 +4359,8 @@ function searchFilesTool(ctx) {
|
|
|
4323
4359
|
}
|
|
4324
4360
|
const resolved2 = resolveInRoot(ctx, path);
|
|
4325
4361
|
if (!resolved2.ok) return resolved2.error;
|
|
4362
|
+
const refusal = dependencyInternalsRefusal(ctx, resolved2.target);
|
|
4363
|
+
if (refusal) return refusal;
|
|
4326
4364
|
try {
|
|
4327
4365
|
await stat2(resolved2.target);
|
|
4328
4366
|
} catch (err) {
|
|
@@ -4347,7 +4385,9 @@ function searchFilesTool(ctx) {
|
|
|
4347
4385
|
let workerFailed = false;
|
|
4348
4386
|
try {
|
|
4349
4387
|
try {
|
|
4350
|
-
const files = await searchableFiles(ctx.root, resolved2.target)
|
|
4388
|
+
const files = (await searchableFiles(ctx.root, resolved2.target)).filter(
|
|
4389
|
+
(file) => !dependencyInternalsRefusal(ctx, file)
|
|
4390
|
+
);
|
|
4351
4391
|
const rootPath = await realpath(ctx.root);
|
|
4352
4392
|
for (const [fileIndex, file] of files.entries()) {
|
|
4353
4393
|
const moreFilesRemain = fileIndex < files.length - LINE_NUMBER_OFFSET;
|
|
@@ -5132,6 +5172,9 @@ function runShellTool(ctx, createModel = defaultCreateModel) {
|
|
|
5132
5172
|
if (isFileIOCommand(command)) {
|
|
5133
5173
|
return "Refused: use listFiles or searchFiles to find files, and readFile to read one, instead of a shell file-listing, reading, or search command (ls/find/fd/tree/dir/locate/cat/head/tail/less/more/tac/nl/grep/egrep/fgrep/rg/ack/ag/xxd/hexdump/od/strings).";
|
|
5134
5174
|
}
|
|
5175
|
+
if (commandNamesDependencyInternals(ctx, command)) {
|
|
5176
|
+
return DEPENDENCY_INTERNALS_REFUSAL;
|
|
5177
|
+
}
|
|
5135
5178
|
logger.info({ command, cwd: resolved2.target }, "called runShell tool");
|
|
5136
5179
|
const reviewed = await serializePrompt(
|
|
5137
5180
|
() => runReviewedCommand(ctx, command, resolved2.target)
|
|
@@ -5444,6 +5487,14 @@ function withCachedHistory(messages) {
|
|
|
5444
5487
|
}
|
|
5445
5488
|
];
|
|
5446
5489
|
}
|
|
5490
|
+
function isAcceptedReportResult(result) {
|
|
5491
|
+
return result.toolName === "reportStatus" && isAcceptedReport(result.output);
|
|
5492
|
+
}
|
|
5493
|
+
function reportAccepted({
|
|
5494
|
+
steps
|
|
5495
|
+
}) {
|
|
5496
|
+
return steps.at(-1)?.toolResults?.some(isAcceptedReportResult) ?? false;
|
|
5497
|
+
}
|
|
5447
5498
|
function isMissingReportRetry(kind) {
|
|
5448
5499
|
return kind === "missingReport" || incompleteReasonOf(kind) !== void 0;
|
|
5449
5500
|
}
|
|
@@ -5563,10 +5614,7 @@ async function runAgentAttempt(req, attempt, retryReason) {
|
|
|
5563
5614
|
tools: req.tools
|
|
5564
5615
|
}),
|
|
5565
5616
|
toolChoice: "required",
|
|
5566
|
-
stopWhen: [
|
|
5567
|
-
hasToolCall("reportStatus"),
|
|
5568
|
-
stepCountIs(maxSteps)
|
|
5569
|
-
],
|
|
5617
|
+
stopWhen: [reportAccepted, stepCountIs(maxSteps)],
|
|
5570
5618
|
prepareStep: ({ stepNumber, messages }) => ({
|
|
5571
5619
|
messages: withCachedHistory(messages),
|
|
5572
5620
|
...stepNumber >= maxSteps - 1 && {
|
|
@@ -5648,7 +5696,7 @@ async function runAgentAttempt(req, attempt, retryReason) {
|
|
|
5648
5696
|
"tool usage"
|
|
5649
5697
|
);
|
|
5650
5698
|
const toolResults = await stream.toolResults;
|
|
5651
|
-
const report = [...toolResults].reverse().find(
|
|
5699
|
+
const report = [...toolResults].reverse().find(isAcceptedReportResult);
|
|
5652
5700
|
if (!report) {
|
|
5653
5701
|
logger.error(
|
|
5654
5702
|
{
|
|
@@ -6995,7 +7043,8 @@ function ingestionRetryInstruction(reason, detail) {
|
|
|
6995
7043
|
}
|
|
6996
7044
|
function validationRetryInstructions(validation) {
|
|
6997
7045
|
return [
|
|
6998
|
-
`Implementation insufficient. Address these findings before reporting completion: ${validation.additionalInstructions ?? validation.summary}
|
|
7046
|
+
`Implementation insufficient. Address these findings before reporting completion: ${validation.additionalInstructions ?? validation.summary}`,
|
|
7047
|
+
"Apply these fixes first, with the fewest edits. When a finding names a fix, apply that fix instead of studying the API again."
|
|
6999
7048
|
];
|
|
7000
7049
|
}
|
|
7001
7050
|
async function pathExists(path) {
|
|
@@ -7067,7 +7116,7 @@ function validationRunInstructions(plan, attempt) {
|
|
|
7067
7116
|
function retryTypeCheckInstructions(plan) {
|
|
7068
7117
|
if (!plan.run) return [];
|
|
7069
7118
|
return [
|
|
7070
|
-
"The developer approved the type check.
|
|
7119
|
+
"The developer approved the type check. Run it once with the project's existing command right after you apply the fixes, before other work. Do not install dependencies, use npx, dlx, or another package runner, or use an autofix option. Fix the errors that your changes cause, and name any error that remains in the summary."
|
|
7071
7120
|
];
|
|
7072
7121
|
}
|
|
7073
7122
|
async function resolveIngestionSource(ctx, repoRoot) {
|
|
@@ -7238,7 +7287,7 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
|
|
|
7238
7287
|
async function runImplementationUseCase(currentUseCase, extraInstructions = [], isRetry = false) {
|
|
7239
7288
|
if (agentRuns > 0) ctx.recordStepExecution();
|
|
7240
7289
|
agentRuns += 1;
|
|
7241
|
-
const toolContext = currentUseCase === "ingestion" ? ingestionTools : makeToolContext(repoRoot);
|
|
7290
|
+
const toolContext = currentUseCase === "ingestion" ? ingestionTools : { ...makeToolContext(repoRoot), dependencyManifestsOnly: true };
|
|
7242
7291
|
try {
|
|
7243
7292
|
return await runAgent({
|
|
7244
7293
|
operation: `${currentUseCase}-implementation`,
|
|
@@ -7283,7 +7332,7 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
|
|
|
7283
7332
|
tools: toolsForUseCase("validation"),
|
|
7284
7333
|
outputSchema: validationOutputSchema,
|
|
7285
7334
|
modelProfile: "validation" /* validation */,
|
|
7286
|
-
toolContext: makeToolContext(repoRoot)
|
|
7335
|
+
toolContext: { ...makeToolContext(repoRoot), dependencyManifestsOnly: true }
|
|
7287
7336
|
});
|
|
7288
7337
|
}
|
|
7289
7338
|
if (useCases.includes("ingestion")) {
|
|
@@ -10024,7 +10073,7 @@ async function resetProjectState() {
|
|
|
10024
10073
|
// package.json with { type: 'json' }
|
|
10025
10074
|
var package_default2 = {
|
|
10026
10075
|
name: "@algolia/wizard",
|
|
10027
|
-
version: "0.
|
|
10076
|
+
version: "0.102.0",
|
|
10028
10077
|
description: "Magically implement Algolia functionality in your codebase",
|
|
10029
10078
|
type: "module",
|
|
10030
10079
|
engines: {
|
|
@@ -95,6 +95,8 @@ Ensure the attributes you map into the component match the entity. 'title' above
|
|
|
95
95
|
- The `item` template renders content only: **no `<a>`, no `href`, no click handler of
|
|
96
96
|
your own, never `stopPropagation`.** The widget's `<li>` owns the click — it sends the
|
|
97
97
|
Insights `click`, closes the panel, clears the active option.
|
|
98
|
+
- Do not pass a top-level `onSelect` to `autocomplete()` to navigate. `getURL` already
|
|
99
|
+
navigates.
|
|
98
100
|
- `getSearchPageURL` sends Enter with nothing highlighted to a full results page; pass it
|
|
99
101
|
only if the app has one. `.getQuery` is optional.
|
|
100
102
|
- TypeScript: type records through the generic, not casts inside templates —
|
|
@@ -87,6 +87,9 @@ Ensure the attributes you map into the component match the entity. 'title' above
|
|
|
87
87
|
- `itemComponent` renders content only: **no `<a>`, no `href`, no `onClick` beyond the
|
|
88
88
|
`onSelect` it is handed, never `stopPropagation`.** The widget's `<li>` owns the click —
|
|
89
89
|
it sends the Insights `click`, closes the panel, clears the active option.
|
|
90
|
+
- Do not pass a top-level `onSelect` to `<Autocomplete>` (for example to call
|
|
91
|
+
`router.push`). `getURL` already navigates. The top-level callback can receive a
|
|
92
|
+
`SyntheticEvent` instead of `{ item }`, so reading `item` from it fails the type check.
|
|
90
93
|
- `getSearchPageURL` sends Enter with nothing highlighted to a full results page; pass it
|
|
91
94
|
only if the app has one. `.getQuery` is optional.
|
|
92
95
|
- TypeScript: type records through the generic, not casts inside `itemComponent` —
|