@algolia/wizard 0.92.0 → 0.94.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 +63 -21
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2384,7 +2384,7 @@ async function ensureApplication(resumeAppId) {
|
|
|
2384
2384
|
// package.json
|
|
2385
2385
|
var package_default = {
|
|
2386
2386
|
name: "@algolia/wizard",
|
|
2387
|
-
version: "0.
|
|
2387
|
+
version: "0.94.0",
|
|
2388
2388
|
description: "Magically implement Algolia functionality in your codebase",
|
|
2389
2389
|
type: "module",
|
|
2390
2390
|
engines: {
|
|
@@ -5282,13 +5282,37 @@ function isProxyInactivityRejection(err) {
|
|
|
5282
5282
|
const cause = RetryError.isInstance(err) ? err.lastError : err;
|
|
5283
5283
|
return APICallError.isInstance(cause) && cause.statusCode === 401 && cause.responseBody === PROXY_REJECTION_BODY && cause.responseHeaders?.[PROXY_AUTH_REJECTED_HEADER2] === void 0;
|
|
5284
5284
|
}
|
|
5285
|
+
var INCOMPLETE_CAUSES = {
|
|
5286
|
+
stepLimit: {
|
|
5287
|
+
kind: "missingReportAtStepLimit",
|
|
5288
|
+
reason: "reached its step limit"
|
|
5289
|
+
},
|
|
5290
|
+
truncated: {
|
|
5291
|
+
kind: "missingReportTruncated",
|
|
5292
|
+
reason: "was cut off by the output token limit"
|
|
5293
|
+
},
|
|
5294
|
+
stopped: {
|
|
5295
|
+
kind: "missingReportStopped",
|
|
5296
|
+
reason: "stopped before it finished"
|
|
5297
|
+
}
|
|
5298
|
+
};
|
|
5299
|
+
var INCOMPLETE_CAUSE_ENTRIES = Object.values(INCOMPLETE_CAUSES);
|
|
5300
|
+
function incompleteReasonOf(kind) {
|
|
5301
|
+
return INCOMPLETE_CAUSE_ENTRIES.find((entry) => entry.kind === kind)?.reason;
|
|
5302
|
+
}
|
|
5285
5303
|
var MissingReportError = class extends Error {
|
|
5286
|
-
|
|
5287
|
-
constructor(
|
|
5304
|
+
incompleteCause;
|
|
5305
|
+
constructor(incompleteCause) {
|
|
5288
5306
|
super(MISSING_REPORT_STATUS_ERROR_MESSAGE);
|
|
5289
|
-
this.
|
|
5307
|
+
this.incompleteCause = incompleteCause;
|
|
5290
5308
|
}
|
|
5291
5309
|
};
|
|
5310
|
+
function incompleteCauseOf(stepCount, maxSteps, finishReason) {
|
|
5311
|
+
if (stepCount >= maxSteps) return "stepLimit";
|
|
5312
|
+
if (finishReason === "length") return "truncated";
|
|
5313
|
+
if (finishReason !== "stop") return "stopped";
|
|
5314
|
+
return null;
|
|
5315
|
+
}
|
|
5292
5316
|
var AgentReportedFailureError = class extends Error {
|
|
5293
5317
|
reason;
|
|
5294
5318
|
constructor(reason) {
|
|
@@ -5314,11 +5338,11 @@ function withCachedHistory(messages) {
|
|
|
5314
5338
|
];
|
|
5315
5339
|
}
|
|
5316
5340
|
function isMissingReportRetry(kind) {
|
|
5317
|
-
return kind === "missingReport" || kind
|
|
5341
|
+
return kind === "missingReport" || incompleteReasonOf(kind) !== void 0;
|
|
5318
5342
|
}
|
|
5319
5343
|
function retryKind(err) {
|
|
5320
5344
|
if (err instanceof MissingReportError) {
|
|
5321
|
-
return err.
|
|
5345
|
+
return err.incompleteCause ? INCOMPLETE_CAUSES[err.incompleteCause].kind : "missingReport";
|
|
5322
5346
|
}
|
|
5323
5347
|
if (NoOutputGeneratedError.isInstance(err)) return "transientProvider";
|
|
5324
5348
|
if (APICallError.isInstance(err) && err.isRetryable) {
|
|
@@ -5354,6 +5378,7 @@ async function runAgentAttempt(req, attempt, retryReason) {
|
|
|
5354
5378
|
const profileOptions = providerOptionsForProfile(profileName);
|
|
5355
5379
|
const maxSteps = req.maxSteps ?? profile.maxSteps;
|
|
5356
5380
|
const forceReport = retryReason === "missingReport";
|
|
5381
|
+
const incompleteReason = incompleteReasonOf(retryReason);
|
|
5357
5382
|
const modelOptions = forceReport ? { thinking: { type: "disabled" } } : profileOptions;
|
|
5358
5383
|
logger.info(
|
|
5359
5384
|
{
|
|
@@ -5394,8 +5419,8 @@ async function runAgentAttempt(req, attempt, retryReason) {
|
|
|
5394
5419
|
"The previous attempt ended without reportStatus. Do not repeat side effects. Use the available read tools to inspect existing work if needed, then call reportStatus."
|
|
5395
5420
|
] : [
|
|
5396
5421
|
"The previous attempt ended without reportStatus. Do not repeat side effects. Call reportStatus now."
|
|
5397
|
-
] :
|
|
5398
|
-
|
|
5422
|
+
] : incompleteReason ? [
|
|
5423
|
+
`The previous attempt ${incompleteReason} without reportStatus and may be incomplete. Inspect existing work, finish only the remaining work, avoid repeated side effects, and call reportStatus.`
|
|
5399
5424
|
] : attempt > 0 ? [
|
|
5400
5425
|
"This run is a retry after a transient AI service error. Files, shell commands, or ingestion may already have been applied in this workspace \u2014 inspect what is already there and continue from it rather than repeating that work."
|
|
5401
5426
|
] : []
|
|
@@ -5527,8 +5552,9 @@ async function runAgentAttempt(req, attempt, retryReason) {
|
|
|
5527
5552
|
},
|
|
5528
5553
|
"Agent finished without calling reportStatus"
|
|
5529
5554
|
);
|
|
5530
|
-
|
|
5531
|
-
|
|
5555
|
+
throw new MissingReportError(
|
|
5556
|
+
incompleteCauseOf(stepCount, maxSteps, finishReason)
|
|
5557
|
+
);
|
|
5532
5558
|
}
|
|
5533
5559
|
const result = report.output;
|
|
5534
5560
|
if (result.status !== "success") {
|
|
@@ -6381,7 +6407,8 @@ function sourceSpecificInstructions(input) {
|
|
|
6381
6407
|
"Read each record from its real local source at the confirmed entity paths.",
|
|
6382
6408
|
"Never fabricate, hardcode, or use placeholder records.",
|
|
6383
6409
|
"Add env vars for any local source access (DB URL, API base, file paths) that is not a fixed repo path.",
|
|
6384
|
-
"To read a database, use the database client or ORM that the project already declares in its manifest. Never install a database driver or ORM. If the project declares none, report that limitation instead of adding one."
|
|
6410
|
+
"To read a database, use the database client or ORM that the project already declares in its manifest. Never install a database driver or ORM. If the project declares none, report that limitation instead of adding one.",
|
|
6411
|
+
"Prefer a server-side credential (a service-role, secret, or admin key, or a database password) over a client-side or public key (for example an anon or publishable key, or any key the project exposes to its frontend) when the source has both: public keys are subject to the source's access rules and can return zero records without an error. Use a public key only when the source offers nothing else. Check the connection to the source before you check for its credential, and make that connection check work without the credential, so an unreachable service is never reported as a missing credential. If the credential the script needs is not in the environment, the script must print an error that names the variable and where the developer finds it, then exit with an error. Never install a client library or driver to work around a missing credential."
|
|
6385
6412
|
],
|
|
6386
6413
|
fileUpload: [
|
|
6387
6414
|
`Records come from the developer's file, already copied into the project at "${input.uploadFilePath}". Read and parse that exact file.`,
|
|
@@ -6437,7 +6464,7 @@ function ingestionInstructions(input) {
|
|
|
6437
6464
|
] : [],
|
|
6438
6465
|
`When the script is finished, decide the exact command and cwd you will use to run it. Make sure that the script path in the command resolves from that cwd to the filePath. Then call reviewScript with that filePath, command, cwd, the exact selected entityName, and usesGeneratedRecords set to ${input.ingestionSource === "generated"}. Wait for the developer to review it because running it writes records to a live index. Do not run it before that call returns. If you change the command or cwd after a failed run, call reviewScript again before runShell.`,
|
|
6439
6466
|
'Then, without changing directories, run the script yourself via runShell using the exact same command and cwd. Report the exact command you ran as "ingestCommand", with no cwd note or other text, so the developer can re-run it. Its explanation must say that running it writes records to Algolia.',
|
|
6440
|
-
"When the script reads from a database or another service, find how the project connects to it locally (env files, README, socket or TCP settings). If that connection needs a local service, such as a database proxy (for example cloud-sql-proxy) or a
|
|
6467
|
+
"When the script reads from a database or another service, find how the project connects to it locally (env files, README, the service's own config file for its host and port, socket or TCP settings). Use the host and port that config sets, not a default. If that connection needs a local service, such as a database proxy (for example cloud-sql-proxy), a tunnel, or a service the project starts with its own CLI or scripts (not necessarily Docker Compose), make the script check the connection before it reads. If the check fails, the script must print an error that names the service, then print exactly one last line to stdout in the form `ALGOLIA_WIZARD_START_HINT=<command>`, where <command> is the command from the project docs or scripts (README, package.json scripts, Makefile) that starts the service, and exit with an error. Omit that line when neither names a start command.",
|
|
6441
6468
|
"Make sure that the start command and the script connect to the same address (the same socket path, or the same host and port). If the project env points at an address that only a deployed environment has, such as a /cloudsql socket, make the script connect to the address of the start command. Set that address in the script before it loads the project database module. Do not edit project env or config files for this.",
|
|
6442
6469
|
"When the script uses the project database client or ORM, load that client's env file (the project .env the client already reads) so credentials such as DB user, password, and database name are present. Load the wizard Algolia .env first, then the project .env, so Algolia keys win under dotenv versions that ignore `override`. Do not rely on `override: true`.",
|
|
6443
6470
|
"If external data access fails, do not run authentication commands, change accounts or machine configuration, or start proxies, containers, or services.",
|
|
@@ -6675,6 +6702,12 @@ function parseIngestRecordCount(output) {
|
|
|
6675
6702
|
const count = Number(match[1]);
|
|
6676
6703
|
return Number.isFinite(count) ? count : void 0;
|
|
6677
6704
|
}
|
|
6705
|
+
function indexedNothing(execution) {
|
|
6706
|
+
return parseIngestRecordCount(execution.output ?? "") === 0;
|
|
6707
|
+
}
|
|
6708
|
+
function ranButIndexedNothing(execution) {
|
|
6709
|
+
return execution.approved && execution.exitCode === 0 && !execution.timedOut && indexedNothing(execution);
|
|
6710
|
+
}
|
|
6678
6711
|
var START_HINT_LINE = /^ALGOLIA_WIZARD_START_HINT=(.*)$/gm;
|
|
6679
6712
|
function parseStartHint(output) {
|
|
6680
6713
|
const matches = [...(output ?? "").matchAll(START_HINT_LINE)];
|
|
@@ -6696,7 +6729,7 @@ function ingestOutcome(executions, repoRoot, ingestCommand) {
|
|
|
6696
6729
|
(e) => parseIngestRecordCount(e.output ?? "") != null
|
|
6697
6730
|
);
|
|
6698
6731
|
const succeeded = newestFirst.filter(
|
|
6699
|
-
(e) => e.approved && e.exitCode === 0 && !e.timedOut
|
|
6732
|
+
(e) => e.approved && e.exitCode === 0 && !e.timedOut && !indexedNothing(e)
|
|
6700
6733
|
);
|
|
6701
6734
|
const run2 = succeeded.find(matchesReportedCommand) ?? succeeded.find((e) => withCount.includes(e));
|
|
6702
6735
|
const runs = executions.filter(
|
|
@@ -6705,7 +6738,9 @@ function ingestOutcome(executions, repoRoot, ingestCommand) {
|
|
|
6705
6738
|
return {
|
|
6706
6739
|
run: run2,
|
|
6707
6740
|
attempt: ingestCommand ? newestFirst.find(matchesReportedCommand) : void 0,
|
|
6708
|
-
recordCount: parseIngestRecordCount(
|
|
6741
|
+
recordCount: parseIngestRecordCount(
|
|
6742
|
+
withCount.find((e) => !indexedNothing(e))?.output ?? ""
|
|
6743
|
+
),
|
|
6709
6744
|
attempts: run2 && !matchesReportedCommand(run2) ? runs + 1 : runs
|
|
6710
6745
|
};
|
|
6711
6746
|
}
|
|
@@ -6785,9 +6820,13 @@ function noRunReason({
|
|
|
6785
6820
|
}
|
|
6786
6821
|
return "no successful run was recorded";
|
|
6787
6822
|
}
|
|
6823
|
+
var EMPTY_INGEST_DETAIL = "The script read no records. A client-side or public key can return no rows because of access rules, so check that it reads with a server-side credential and that the data source has data.";
|
|
6788
6824
|
function ingestFailure(attempt, missingRunReason = "no successful run was recorded") {
|
|
6789
6825
|
if (!attempt) return { reason: missingRunReason };
|
|
6790
6826
|
if (!attempt.approved) return { reason: "you declined to run it" };
|
|
6827
|
+
if (ranButIndexedNothing(attempt)) {
|
|
6828
|
+
return { reason: "it ran but indexed 0 records", detail: EMPTY_INGEST_DETAIL };
|
|
6829
|
+
}
|
|
6791
6830
|
const detail = errorLine(attempt.output);
|
|
6792
6831
|
if (attempt.timedOut) {
|
|
6793
6832
|
const seconds = Math.round((attempt.durationMs ?? 0) / 1e3);
|
|
@@ -6828,8 +6867,8 @@ function briefSummary(summary) {
|
|
|
6828
6867
|
if (!firstLine) return "no summary given";
|
|
6829
6868
|
return firstLine.length > ERROR_SUMMARY_MAX_CHARS ? `${firstLine.slice(0, ERROR_SUMMARY_MAX_CHARS - 1)}\u2026` : firstLine;
|
|
6830
6869
|
}
|
|
6831
|
-
function ingestionRetryInstruction(reason) {
|
|
6832
|
-
return `The previous ingestion attempt ended with no successful run: ${reason}
|
|
6870
|
+
function ingestionRetryInstruction(reason, detail) {
|
|
6871
|
+
return `The previous ingestion attempt ended with no successful run: ${reason}.${detail ? ` ${detail}` : ""} Look in "${INGEST_DIR}/" for a script from that attempt and finish or fix it instead of starting over. Then call reviewScript and run the script as described above.`;
|
|
6833
6872
|
}
|
|
6834
6873
|
function validationRetryInstructions(validation) {
|
|
6835
6874
|
return [
|
|
@@ -7166,19 +7205,22 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
|
|
|
7166
7205
|
await runIngestionAgent();
|
|
7167
7206
|
let outcome = ingestOutcome(executions, repoRoot, ingestCommand);
|
|
7168
7207
|
let failureAcknowledged = false;
|
|
7169
|
-
while (!outcome.run && !outcome.attempt) {
|
|
7170
|
-
const reason = await currentNoRunReason();
|
|
7208
|
+
while (!outcome.run && (!outcome.attempt || ranButIndexedNothing(outcome.attempt))) {
|
|
7209
|
+
const { reason, detail } = outcome.attempt ? ingestFailure(outcome.attempt) : { reason: await currentNoRunReason(), detail: void 0 };
|
|
7171
7210
|
const choice = await ctx.requestUserInput({
|
|
7172
7211
|
prompt: INGEST_AGENT_RETRY_PROMPT,
|
|
7173
7212
|
promptType: "multipleChoice",
|
|
7174
7213
|
options: [INGEST_RETRY.retry, INGEST_RETRY.skip],
|
|
7175
|
-
messages: [
|
|
7214
|
+
messages: [
|
|
7215
|
+
`\u26A0\uFE0F Records were not indexed \u2014 ${reason}.`,
|
|
7216
|
+
...detail ? [detail] : []
|
|
7217
|
+
]
|
|
7176
7218
|
});
|
|
7177
7219
|
if (choice !== INGEST_RETRY.retry) {
|
|
7178
7220
|
failureAcknowledged = true;
|
|
7179
7221
|
break;
|
|
7180
7222
|
}
|
|
7181
|
-
await runIngestionAgent([ingestionRetryInstruction(reason)]);
|
|
7223
|
+
await runIngestionAgent([ingestionRetryInstruction(reason, detail)]);
|
|
7182
7224
|
outcome = ingestOutcome(executions, repoRoot, ingestCommand);
|
|
7183
7225
|
}
|
|
7184
7226
|
while (!failureAcknowledged && !outcome.run && outcome.attempt?.approved) {
|
|
@@ -9833,7 +9875,7 @@ async function resetProjectState() {
|
|
|
9833
9875
|
// package.json with { type: 'json' }
|
|
9834
9876
|
var package_default2 = {
|
|
9835
9877
|
name: "@algolia/wizard",
|
|
9836
|
-
version: "0.
|
|
9878
|
+
version: "0.94.0",
|
|
9837
9879
|
description: "Magically implement Algolia functionality in your codebase",
|
|
9838
9880
|
type: "module",
|
|
9839
9881
|
engines: {
|