@aident-ai/cli 0.3.0 → 0.3.1-rc.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/cli.mjs +314 -82
- package/dist/dsh.mjs +2970 -47
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -3354,7 +3354,7 @@ import { mkdir as mkdir2 } from "node:fs/promises";
|
|
|
3354
3354
|
import { dirname as dirname2, posix, resolve as resolve2, sep } from "node:path";
|
|
3355
3355
|
import { Readable, Transform } from "node:stream";
|
|
3356
3356
|
import { pipeline } from "node:stream/promises";
|
|
3357
|
-
import { createGunzip } from "node:zlib";
|
|
3357
|
+
import { createGunzip, gzipSync } from "node:zlib";
|
|
3358
3358
|
|
|
3359
3359
|
// ../../node_modules/tar-stream/index.js
|
|
3360
3360
|
var $extract = require_extract();
|
|
@@ -7191,11 +7191,13 @@ var AgentSkillBundleVersionSchema = stringType().regex(/^[0-9]+\.[0-9]+\.[0-9]+(
|
|
|
7191
7191
|
var AgentSkillBundleSha256Schema = stringType().regex(/^[a-f0-9]{64}$/);
|
|
7192
7192
|
var AgentSkillBundleGitShaSchema = stringType().regex(/^[a-f0-9]{40}$/);
|
|
7193
7193
|
var AgentSkillBundleRightsBasisSchema = nativeEnumType(AgentSkillBundleRightsBasis);
|
|
7194
|
+
var AgentSkillBundleSourcePathSchema = stringType().min(1).max(300).regex(/^[A-Za-z0-9_.-]+(?:\/[A-Za-z0-9_.-]+)*$/).refine((value) => value.split("/").every((segment) => segment !== "." && segment !== ".."));
|
|
7194
7195
|
var AgentSkillBundlePublishManifestSchema = objectType({
|
|
7195
7196
|
name: AgentSkillBundleNameSchema,
|
|
7196
7197
|
version: AgentSkillBundleVersionSchema,
|
|
7197
7198
|
sourceOwner: stringType().regex(/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$/).max(39).refine((value) => !value.includes("--")),
|
|
7198
7199
|
sourceRepository: stringType().regex(/^[A-Za-z0-9_.][A-Za-z0-9_.-]{0,99}$/).refine((value) => value !== "." && value !== ".."),
|
|
7200
|
+
sourcePath: AgentSkillBundleSourcePathSchema.optional(),
|
|
7199
7201
|
sourceCommit: AgentSkillBundleGitShaSchema,
|
|
7200
7202
|
sourceTree: AgentSkillBundleGitShaSchema,
|
|
7201
7203
|
expectedSha256: AgentSkillBundleSha256Schema,
|
|
@@ -7387,25 +7389,9 @@ async function installAgentSkillBundle(descriptorValue, options = {}, injected =
|
|
|
7387
7389
|
const descriptor = AgentSkillBundleInstallDescriptorSchema.parse(descriptorValue);
|
|
7388
7390
|
const home = options.home ?? homedir2();
|
|
7389
7391
|
const env = options.env ?? process.env;
|
|
7390
|
-
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
await mkdir3(stateRoot, { recursive: true, mode: 448 });
|
|
7394
|
-
const lock = await tryAcquireDirectoryLock(join3(stateRoot, "install.lock"));
|
|
7395
|
-
if (!lock)
|
|
7396
|
-
throw new Error(`Another ${descriptor.name} installation is already running`);
|
|
7397
|
-
try {
|
|
7398
|
-
if (!await pathExists(releaseDirectory)) {
|
|
7399
|
-
const archive = await downloadArchive(descriptor, injected.fetch ?? fetch);
|
|
7400
|
-
await materializeRelease(archive, descriptor, releasesRoot, releaseDirectory);
|
|
7401
|
-
} else {
|
|
7402
|
-
const existingRelease = await lstat2(releaseDirectory);
|
|
7403
|
-
if (!existingRelease.isDirectory()) {
|
|
7404
|
-
throw new Error(`Existing agent Skill release is not a directory: ${releaseDirectory}`);
|
|
7405
|
-
}
|
|
7406
|
-
await assertInstalledSkillIdentity(releaseDirectory, descriptor.name);
|
|
7407
|
-
}
|
|
7408
|
-
const targets = await reconcileTargets(descriptor.name, releaseDirectory, releasesRoot, home, env);
|
|
7392
|
+
return withInstallLock(descriptor.name, home, async () => {
|
|
7393
|
+
const { releaseDirectory } = await prepareRelease(descriptor, home, injected.fetch ?? fetch);
|
|
7394
|
+
const targets = await reconcileTargets(descriptor.name, releaseDirectory, dirname3(releaseDirectory), home, env);
|
|
7409
7395
|
return {
|
|
7410
7396
|
name: descriptor.name,
|
|
7411
7397
|
version: descriptor.version,
|
|
@@ -7414,6 +7400,37 @@ async function installAgentSkillBundle(descriptorValue, options = {}, injected =
|
|
|
7414
7400
|
success: targets.every((target) => target.status !== "conflict" /* Conflict */ && target.status !== "failed" /* Failed */),
|
|
7415
7401
|
targets
|
|
7416
7402
|
};
|
|
7403
|
+
});
|
|
7404
|
+
}
|
|
7405
|
+
async function prepareAgentSkillBundleRelease(descriptorValue, options = {}, injected = {}) {
|
|
7406
|
+
const descriptor = AgentSkillBundleInstallDescriptorSchema.parse(descriptorValue);
|
|
7407
|
+
const home = options.home ?? homedir2();
|
|
7408
|
+
return withInstallLock(descriptor.name, home, () => prepareRelease(descriptor, home, injected.fetch ?? fetch));
|
|
7409
|
+
}
|
|
7410
|
+
async function prepareRelease(descriptor, home, fetchImpl) {
|
|
7411
|
+
const stateRoot = join3(home, ".aident", "skills", "internal", descriptor.name);
|
|
7412
|
+
const releasesRoot = join3(stateRoot, "releases");
|
|
7413
|
+
const releaseDirectory = join3(releasesRoot, descriptor.artifactSha256);
|
|
7414
|
+
if (!await pathExists(releaseDirectory)) {
|
|
7415
|
+
const archive = await downloadArchive(descriptor, fetchImpl);
|
|
7416
|
+
await materializeRelease(archive, descriptor, releasesRoot, releaseDirectory);
|
|
7417
|
+
} else {
|
|
7418
|
+
const existingRelease = await lstat2(releaseDirectory);
|
|
7419
|
+
if (!existingRelease.isDirectory()) {
|
|
7420
|
+
throw new Error(`Existing agent Skill release is not a directory: ${releaseDirectory}`);
|
|
7421
|
+
}
|
|
7422
|
+
await assertInstalledSkillIdentity(releaseDirectory, descriptor.name);
|
|
7423
|
+
}
|
|
7424
|
+
return { descriptor, releaseDirectory };
|
|
7425
|
+
}
|
|
7426
|
+
async function withInstallLock(name, home, run) {
|
|
7427
|
+
const stateRoot = join3(home, ".aident", "skills", "internal", name);
|
|
7428
|
+
await mkdir3(stateRoot, { recursive: true, mode: 448 });
|
|
7429
|
+
const lock = await tryAcquireDirectoryLock(join3(stateRoot, "install.lock"));
|
|
7430
|
+
if (!lock)
|
|
7431
|
+
throw new Error(`Another ${name} installation is already running`);
|
|
7432
|
+
try {
|
|
7433
|
+
return await run();
|
|
7417
7434
|
} finally {
|
|
7418
7435
|
await lock.release();
|
|
7419
7436
|
}
|
|
@@ -7689,7 +7706,7 @@ function readLine(prompt, options = {}) {
|
|
|
7689
7706
|
var CLIENT_NAME = "aident-cli";
|
|
7690
7707
|
var LOOPBACK_HOST = "127.0.0.1";
|
|
7691
7708
|
var LOGIN_OPEN_TIMEOUT_MS = 90 * 1000;
|
|
7692
|
-
var LOGIN_COMPLETE_TIMEOUT_AFTER_OPENED_MS =
|
|
7709
|
+
var LOGIN_COMPLETE_TIMEOUT_AFTER_OPENED_MS = 30 * 60 * 1000;
|
|
7693
7710
|
var LOGIN_OPENED_MESSAGE = `User opened the Aident login window. They have ${LOGIN_COMPLETE_TIMEOUT_AFTER_OPENED_MS / 60000} minutes to finish; if it fails, run \`aident login --oob\`, share the URL, and ask for the verification code.`;
|
|
7694
7711
|
async function login(options) {
|
|
7695
7712
|
const baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
@@ -8167,7 +8184,7 @@ function getConfigFile() {
|
|
|
8167
8184
|
function getConfigFileForHome(home) {
|
|
8168
8185
|
return join4(getAidentDir(home), "config.json");
|
|
8169
8186
|
}
|
|
8170
|
-
var DEFAULT_BASE_URL = "https://loadout.aident.ai"?.trim() || "https://loadout.aident.ai";
|
|
8187
|
+
var DEFAULT_BASE_URL = "https://rc.loadout.aident.ai"?.trim() || "https://loadout.aident.ai";
|
|
8171
8188
|
var CONFIG_KEYS = ["baseUrl", "packages"];
|
|
8172
8189
|
async function readConfig(configFile = getConfigFile()) {
|
|
8173
8190
|
try {
|
|
@@ -8460,7 +8477,7 @@ function serializeLoadoutSkillPackage(skillPackage) {
|
|
|
8460
8477
|
}
|
|
8461
8478
|
|
|
8462
8479
|
// src/version.ts
|
|
8463
|
-
var VERSION = "0.3.0";
|
|
8480
|
+
var VERSION = "0.3.1-rc.0";
|
|
8464
8481
|
var DESKTOP_VERSION = process.env.AIDENT_DESKTOP_VERSION?.trim() || undefined;
|
|
8465
8482
|
var DESKTOP_CHANNEL = parseDesktopChannel(process.env.AIDENT_DESKTOP_CHANNEL);
|
|
8466
8483
|
function parseDesktopChannel(value) {
|
|
@@ -9353,7 +9370,7 @@ var LoadoutFavoriteSkillsUpdateSchema = objectType({
|
|
|
9353
9370
|
syncRequired: booleanType()
|
|
9354
9371
|
}).strict();
|
|
9355
9372
|
function getLoadoutFavoriteSkillsStateToken(skills) {
|
|
9356
|
-
const state = skills.map(({ name, artifactVersionId }) => ({ name, artifactVersionId })).sort((left, right) => left.name.localeCompare(right.name));
|
|
9373
|
+
const state = skills.map(({ name, artifactVersionId, deliveryRevision }) => ({ name, artifactVersionId, deliveryRevision })).sort((left, right) => left.name.localeCompare(right.name));
|
|
9357
9374
|
return createHash3("sha256").update(JSON.stringify(state)).digest("hex");
|
|
9358
9375
|
}
|
|
9359
9376
|
|
|
@@ -9517,10 +9534,11 @@ var KNOWN_CLEAN_LOADOUT_SKILL_REQUIRED_FILE_GIT_BLOB_SHA1 = {
|
|
|
9517
9534
|
}
|
|
9518
9535
|
]
|
|
9519
9536
|
};
|
|
9520
|
-
async function fetchLoadoutSkillMetadata(baseUrl) {
|
|
9537
|
+
async function fetchLoadoutSkillMetadata(baseUrl, signal) {
|
|
9521
9538
|
const metadataUrl = `${baseUrl.replace(/\/+$/, "")}/.well-known/loadout-skill.json`;
|
|
9522
9539
|
const res = await fetch(metadataUrl, {
|
|
9523
9540
|
method: "GET",
|
|
9541
|
+
signal,
|
|
9524
9542
|
headers: {
|
|
9525
9543
|
"User-Agent": `@aident-ai/cli/${VERSION}`,
|
|
9526
9544
|
[AIDENT_UPDATE_PROTOCOL_HEADER]: AIDENT_UPDATE_PROTOCOL_VERSION
|
|
@@ -10090,7 +10108,7 @@ function isExpired(creds) {
|
|
|
10090
10108
|
|
|
10091
10109
|
// src/loadoutFavoriteSkills.ts
|
|
10092
10110
|
import { createHash as createHash5 } from "node:crypto";
|
|
10093
|
-
import { lstat as lstat5, mkdir as mkdir8, readFile as readFile8, readlink, rename as rename4, rm as rm3, symlink as symlink3, writeFile as writeFile6 } from "node:fs/promises";
|
|
10111
|
+
import { cp, lstat as lstat5, mkdir as mkdir8, readFile as readFile8, readlink, rename as rename4, rm as rm3, symlink as symlink3, writeFile as writeFile6 } from "node:fs/promises";
|
|
10094
10112
|
import { homedir as homedir5 } from "node:os";
|
|
10095
10113
|
import path from "node:path";
|
|
10096
10114
|
|
|
@@ -10169,6 +10187,8 @@ function assertPackage(pkg) {
|
|
|
10169
10187
|
}
|
|
10170
10188
|
if (packageBytes > LOADOUT_SKILL_MAX_PACKAGE_BYTES)
|
|
10171
10189
|
throw new Error(`Package is too large: ${pkg.name}`);
|
|
10190
|
+
if (pkg.bundle)
|
|
10191
|
+
AgentSkillBundleInstallDescriptorSchema.parse(pkg.bundle);
|
|
10172
10192
|
}
|
|
10173
10193
|
function quoteYaml(value) {
|
|
10174
10194
|
return JSON.stringify(value);
|
|
@@ -10211,7 +10231,7 @@ async function readManifest(home, env) {
|
|
|
10211
10231
|
throw new Error("Unsupported manifest");
|
|
10212
10232
|
const harnessRoots = new Set(getHarnessHosts(home, env).map(({ root }) => path.join(root, "skills")));
|
|
10213
10233
|
for (const skill of value.skills) {
|
|
10214
|
-
if (!LOADOUT_SKILL_NAME_PATTERN.test(skill.name) || !isCanonicalUuid(skill.artifactVersionId) || skill.displayName !== undefined && typeof skill.displayName !== "string" || skill.summary !== undefined && typeof skill.summary !== "string" || !/^loadout-[a-z0-9-]+-[0-9a-f]{8}$/.test(skill.commandName) || skill.installPath !== path.join(getCanonicalRoot(home, env), skill.commandName) || skill.linkPaths.some((linkPath) => !harnessRoots.has(path.dirname(linkPath)) || path.basename(linkPath) !== skill.commandName)) {
|
|
10234
|
+
if (!LOADOUT_SKILL_NAME_PATTERN.test(skill.name) || !isCanonicalUuid(skill.artifactVersionId) || skill.displayName !== undefined && typeof skill.displayName !== "string" || skill.summary !== undefined && typeof skill.summary !== "string" || skill.deliveryRevision !== undefined && !/^[a-f0-9]{64}$/.test(skill.deliveryRevision) || !/^loadout-[a-z0-9-]+-[0-9a-f]{8}$/.test(skill.commandName) || skill.installPath !== path.join(getCanonicalRoot(home, env), skill.commandName) || skill.linkPaths.some((linkPath) => !harnessRoots.has(path.dirname(linkPath)) || path.basename(linkPath) !== skill.commandName)) {
|
|
10215
10235
|
throw new Error("Invalid favorite Skills ownership manifest");
|
|
10216
10236
|
}
|
|
10217
10237
|
}
|
|
@@ -10245,7 +10265,11 @@ async function removeOwnedSkill(skill) {
|
|
|
10245
10265
|
if (await pathExists3(skill.installPath))
|
|
10246
10266
|
await rm3(skill.installPath, { recursive: true });
|
|
10247
10267
|
}
|
|
10248
|
-
async function
|
|
10268
|
+
async function writeBundlePackage(directory, pkg, releaseDirectory) {
|
|
10269
|
+
await cp(releaseDirectory, directory, { recursive: true });
|
|
10270
|
+
await writeFile6(path.join(directory, LOADOUT_SKILL_ENTRYPOINT), entrypointContent(pkg, await readFile8(path.join(releaseDirectory, LOADOUT_SKILL_ENTRYPOINT), "utf8")));
|
|
10271
|
+
}
|
|
10272
|
+
async function reconcileLoadoutFavoriteSkills(payload, home = getHome(), env = process.env, injected = {}) {
|
|
10249
10273
|
const manifest = await readManifest(home, env);
|
|
10250
10274
|
const previousByName = new Map(manifest.skills.map((skill) => [skill.name, skill]));
|
|
10251
10275
|
const desiredNames = new Set(payload.packages.map((pkg) => pkg.name));
|
|
@@ -10260,6 +10284,12 @@ async function reconcileLoadoutFavoriteSkills(payload, home = getHome(), env = p
|
|
|
10260
10284
|
if (payload.unavailable.some((name) => desiredNames.has(name))) {
|
|
10261
10285
|
throw new Error("A favorite Skill cannot be both available and unavailable");
|
|
10262
10286
|
}
|
|
10287
|
+
const preparedBundles = new Map;
|
|
10288
|
+
for (const pkg of payload.packages) {
|
|
10289
|
+
if (!pkg.bundle)
|
|
10290
|
+
continue;
|
|
10291
|
+
preparedBundles.set(pkg.name, await (injected.prepareBundleRelease ?? prepareAgentSkillBundleRelease)(pkg.bundle, { home, env }));
|
|
10292
|
+
}
|
|
10263
10293
|
const nextSkills = [];
|
|
10264
10294
|
const result = {
|
|
10265
10295
|
installed: [],
|
|
@@ -10301,21 +10331,26 @@ async function reconcileLoadoutFavoriteSkills(payload, home = getHome(), env = p
|
|
|
10301
10331
|
continue;
|
|
10302
10332
|
}
|
|
10303
10333
|
const allLinksExist = (await Promise.all(linkPaths.map(pathExists3))).every(Boolean);
|
|
10304
|
-
if (previous?.artifactVersionId === pkg.artifactVersionId && previous.displayName === pkg.displayName && previous.summary === pkg.summary && previous.installPath === installPath && previous.linkPaths.length === linkPaths.length && previous.linkPaths.every((linkPath) => linkPaths.includes(linkPath)) && await pathExists3(installPath) && allLinksExist) {
|
|
10334
|
+
if (previous?.artifactVersionId === pkg.artifactVersionId && previous.displayName === pkg.displayName && previous.summary === pkg.summary && previous.deliveryRevision === pkg.bundle?.artifactSha256 && previous.installPath === installPath && previous.linkPaths.length === linkPaths.length && previous.linkPaths.every((linkPath) => linkPaths.includes(linkPath)) && await pathExists3(installPath) && allLinksExist) {
|
|
10305
10335
|
result.unchanged.push(pkg.name);
|
|
10306
10336
|
nextSkills.push(previous);
|
|
10307
10337
|
continue;
|
|
10308
10338
|
}
|
|
10339
|
+
const preparedBundle = preparedBundles.get(pkg.name);
|
|
10309
10340
|
const temporaryPath = `${installPath}.${process.pid}.tmp`;
|
|
10310
10341
|
const backupPath = `${installPath}.${process.pid}.backup`;
|
|
10311
10342
|
await mkdir8(getCanonicalRoot(home, env), { recursive: true });
|
|
10312
10343
|
await rm3(temporaryPath, { recursive: true, force: true });
|
|
10313
10344
|
await rm3(backupPath, { recursive: true, force: true });
|
|
10314
|
-
|
|
10315
|
-
|
|
10316
|
-
|
|
10317
|
-
await mkdir8(
|
|
10318
|
-
|
|
10345
|
+
if (preparedBundle) {
|
|
10346
|
+
await writeBundlePackage(temporaryPath, pkg, preparedBundle.releaseDirectory);
|
|
10347
|
+
} else {
|
|
10348
|
+
await mkdir8(temporaryPath, { recursive: true });
|
|
10349
|
+
for (const file of pkg.files) {
|
|
10350
|
+
const destination = path.join(temporaryPath, ...file.path.split("/"));
|
|
10351
|
+
await mkdir8(path.dirname(destination), { recursive: true });
|
|
10352
|
+
await writeFile6(destination, file.path === LOADOUT_SKILL_ENTRYPOINT ? entrypointContent(pkg, file.content) : file.content);
|
|
10353
|
+
}
|
|
10319
10354
|
}
|
|
10320
10355
|
const createdLinkPaths = [];
|
|
10321
10356
|
let backedUp = false;
|
|
@@ -10350,7 +10385,8 @@ async function reconcileLoadoutFavoriteSkills(payload, home = getHome(), env = p
|
|
|
10350
10385
|
summary: pkg.summary,
|
|
10351
10386
|
commandName: nextCommandName,
|
|
10352
10387
|
installPath,
|
|
10353
|
-
linkPaths
|
|
10388
|
+
linkPaths,
|
|
10389
|
+
...pkg.bundle ? { deliveryRevision: pkg.bundle.artifactSha256 } : {}
|
|
10354
10390
|
});
|
|
10355
10391
|
(previous ? result.updated : result.installed).push(pkg.name);
|
|
10356
10392
|
}
|
|
@@ -11357,7 +11393,7 @@ async function readBoundedResponseBody(response, expectedByteLength, maximumByte
|
|
|
11357
11393
|
|
|
11358
11394
|
// src/minisign.ts
|
|
11359
11395
|
import { createHash as createHash7, createPublicKey, verify } from "node:crypto";
|
|
11360
|
-
var ACTIVE_PUBLIC_KEYS = JSON.parse('{"
|
|
11396
|
+
var ACTIVE_PUBLIC_KEYS = JSON.parse('{"aident-desktop-release-2026-08-v2":"RWSuGigRGuwWblBdVlTya0xk4E3OlM2YOWrxndkGuO5ZN3tq5JdpF45a"}');
|
|
11361
11397
|
var ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
|
11362
11398
|
function verifyMinisign(bytes, signatureText, signingKeyId) {
|
|
11363
11399
|
const encodedKey = ACTIVE_PUBLIC_KEYS[signingKeyId];
|
|
@@ -11395,7 +11431,7 @@ import { chmod, lstat as lstat6, mkdir as mkdir9, open, readFile as readFile10,
|
|
|
11395
11431
|
import { dirname as dirname8, isAbsolute as isAbsolute3, relative as relative2, resolve as resolve4 } from "node:path";
|
|
11396
11432
|
import { promisify } from "node:util";
|
|
11397
11433
|
var execFile2 = promisify(execFileCallback);
|
|
11398
|
-
var
|
|
11434
|
+
var windowsAccountSid;
|
|
11399
11435
|
async function readFileIfPresent(path) {
|
|
11400
11436
|
try {
|
|
11401
11437
|
const entry = await lstat6(path);
|
|
@@ -11471,17 +11507,23 @@ function hasCode3(error, code) {
|
|
|
11471
11507
|
async function protectWindowsPath(path, directory) {
|
|
11472
11508
|
if (process.platform !== "win32")
|
|
11473
11509
|
return;
|
|
11474
|
-
const
|
|
11475
|
-
await execFile2("icacls.exe", [path, "/inheritance:r", "/grant:r",
|
|
11510
|
+
const sid = await getWindowsAccountSid();
|
|
11511
|
+
await execFile2("icacls.exe", [path, "/inheritance:r", "/grant:r", `*${sid}:${directory ? "(OI)(CI)" : ""}F`]);
|
|
11476
11512
|
}
|
|
11477
|
-
|
|
11478
|
-
|
|
11479
|
-
|
|
11513
|
+
function parseWindowsAccountSid(output) {
|
|
11514
|
+
const match = output.toString("latin1").match(/,"(S-1-\d+(?:-\d+)+)"\s*$/);
|
|
11515
|
+
if (!match)
|
|
11516
|
+
throw new Error("Windows account SID is unavailable");
|
|
11517
|
+
return match[1];
|
|
11518
|
+
}
|
|
11519
|
+
async function getWindowsAccountSid() {
|
|
11520
|
+
windowsAccountSid ??= execFile2("whoami.exe", ["/user", "/fo", "csv", "/nh"], { encoding: "buffer" }).then(({ stdout }) => parseWindowsAccountSid(stdout));
|
|
11521
|
+
const pending = windowsAccountSid;
|
|
11480
11522
|
try {
|
|
11481
11523
|
return await pending;
|
|
11482
11524
|
} catch (error) {
|
|
11483
|
-
if (
|
|
11484
|
-
|
|
11525
|
+
if (windowsAccountSid === pending)
|
|
11526
|
+
windowsAccountSid = undefined;
|
|
11485
11527
|
throw error;
|
|
11486
11528
|
}
|
|
11487
11529
|
}
|
|
@@ -11803,22 +11845,51 @@ import { execFile as execFileCallback2 } from "node:child_process";
|
|
|
11803
11845
|
import { constants as constants3 } from "node:fs";
|
|
11804
11846
|
import { access as access2, realpath as realpath5 } from "node:fs/promises";
|
|
11805
11847
|
import { homedir as homedir8 } from "node:os";
|
|
11806
|
-
import { basename as basename3, delimiter as delimiter2, isAbsolute as isAbsolute5, join as join11 } from "node:path";
|
|
11848
|
+
import { basename as basename3, delimiter as delimiter2, isAbsolute as isAbsolute5, join as join11, win32 as win323 } from "node:path";
|
|
11807
11849
|
import { promisify as promisify2 } from "node:util";
|
|
11808
11850
|
var execFile3 = promisify2(execFileCallback2);
|
|
11809
11851
|
var SUPPORTED_SHELLS = new Set(["sh", "bash", "zsh", "dash", "ksh"]);
|
|
11852
|
+
var WINDOWS_ENV_KEYS = new Map([
|
|
11853
|
+
["path", "PATH"],
|
|
11854
|
+
["systemroot", "SystemRoot"],
|
|
11855
|
+
["comspec", "ComSpec"]
|
|
11856
|
+
]);
|
|
11857
|
+
var PROBE_TIMEOUT_DETAIL = "Windows CLI verification timed out; retry after the machine finishes starting up";
|
|
11858
|
+
var WINDOWS_PROBE_CLEANUP_TIMEOUT_MS = 2000;
|
|
11810
11859
|
async function inspectAidentCliEntrypoint(home = homedir8(), env = process.env, platform = process.platform, injected = {}) {
|
|
11860
|
+
if (platform === "win32") {
|
|
11861
|
+
env = Object.fromEntries(Object.entries(env).map(([key, value]) => [WINDOWS_ENV_KEYS.get(key.toLowerCase()) ?? key, value]));
|
|
11862
|
+
}
|
|
11811
11863
|
const resolveNativePath = injected.resolveNativePath ?? (async (homeDirectory) => (await readActiveNativeInstallation(homeDirectory, getActiveCliExecutablePath(env)))?.receipt.cliPath ?? null);
|
|
11812
|
-
const
|
|
11813
|
-
|
|
11864
|
+
const probeTimeoutMs = platform === "win32" ? injected.probeTimeoutMs ?? 1e4 : undefined;
|
|
11865
|
+
if (probeTimeoutMs !== undefined && probeTimeoutMs <= 0)
|
|
11866
|
+
throw new RangeError("Windows probe timeout must be positive");
|
|
11867
|
+
const commandDeadline = probeTimeoutMs ? AbortSignal.timeout(probeTimeoutMs * 2 - Math.min(probeTimeoutMs, WINDOWS_PROBE_CLEANUP_TIMEOUT_MS)) : undefined;
|
|
11868
|
+
const runProbe = injected.execFile ?? ((file, args, env, platform) => runFile(file, args, env, platform, commandDeadline, probeTimeoutMs, injected.spawnProbe));
|
|
11869
|
+
const probe = async (operation) => {
|
|
11870
|
+
let timedOut = false;
|
|
11871
|
+
const executeFile = async (file, args, env, platform) => {
|
|
11872
|
+
try {
|
|
11873
|
+
return await runProbe(file, args, env, platform);
|
|
11874
|
+
} catch (error) {
|
|
11875
|
+
if (platform === "win32" && error instanceof Error && error.name === "TimeoutError")
|
|
11876
|
+
timedOut = true;
|
|
11877
|
+
throw error;
|
|
11878
|
+
}
|
|
11879
|
+
};
|
|
11880
|
+
return { value: await operation(executeFile), timedOut };
|
|
11881
|
+
};
|
|
11882
|
+
const [resolution, nativePath] = await Promise.all([
|
|
11883
|
+
probe((executeFile) => injected.resolveActiveCommand ? injected.resolveActiveCommand(env, platform) : resolveActiveAidentCommand(env, platform, executeFile)),
|
|
11814
11884
|
resolveNativePath(home)
|
|
11815
11885
|
]);
|
|
11886
|
+
const active = resolution.value;
|
|
11816
11887
|
if (!active) {
|
|
11817
11888
|
return {
|
|
11818
11889
|
ok: false,
|
|
11819
|
-
owner: "missing",
|
|
11890
|
+
owner: resolution.timedOut ? "unknown" /* Unknown */ : "missing",
|
|
11820
11891
|
...nativePath ? { nativePath } : {},
|
|
11821
|
-
detail: nativePath ? "The bundled Aident CLI is installed but the aident command is not available on PATH" : "The aident command is not available on PATH"
|
|
11892
|
+
detail: resolution.timedOut ? PROBE_TIMEOUT_DETAIL : nativePath ? "The bundled Aident CLI is installed but the aident command is not available on PATH" : "The aident command is not available on PATH"
|
|
11822
11893
|
};
|
|
11823
11894
|
}
|
|
11824
11895
|
const resolveRealpath = injected.realpath ?? realpath5;
|
|
@@ -11826,7 +11897,7 @@ async function inspectAidentCliEntrypoint(home = homedir8(), env = process.env,
|
|
|
11826
11897
|
resolveRealpath(active.path).catch(() => active.path),
|
|
11827
11898
|
nativePath ? resolveRealpath(nativePath).catch(() => nativePath) : null
|
|
11828
11899
|
]);
|
|
11829
|
-
const version = await (injected.readVersion
|
|
11900
|
+
const { value: version, timedOut: versionTimedOut } = await probe((executeFile) => injected.readVersion ? injected.readVersion(active.path, active.env) : readAidentCliVersion(active.path, active.env, platform, executeFile));
|
|
11830
11901
|
const requiredVersion = injected.requiredVersion ?? VERSION;
|
|
11831
11902
|
const current = version !== null && isAidentSemver(version) && compareAidentSemver(version, requiredVersion) >= 0;
|
|
11832
11903
|
if (nativeRealpath && activeRealpath === nativeRealpath) {
|
|
@@ -11836,42 +11907,70 @@ async function inspectAidentCliEntrypoint(home = homedir8(), env = process.env,
|
|
|
11836
11907
|
...version ? { version } : {},
|
|
11837
11908
|
activePath: active.path,
|
|
11838
11909
|
nativePath,
|
|
11839
|
-
detail: version ? current ? "The native Aident CLI is the active command" : `The active Aident CLI v${version} must be updated to v${requiredVersion} or newer before onboarding` : "The native Aident CLI could not report its version"
|
|
11910
|
+
detail: version ? current ? "The native Aident CLI is the active command" : `The active Aident CLI v${version} must be updated to v${requiredVersion} or newer before onboarding` : versionTimedOut ? PROBE_TIMEOUT_DETAIL : "The native Aident CLI could not report its version"
|
|
11840
11911
|
};
|
|
11841
11912
|
}
|
|
11842
11913
|
const detectOwnership = injected.detectOwnership ?? detectCliInstallOwnership;
|
|
11843
|
-
const ownership = await detectOwnership(active.path, home, {
|
|
11914
|
+
const { value: ownership, timedOut: ownershipTimedOut } = await probe((executeFile) => detectOwnership(active.path, home, {
|
|
11844
11915
|
platform,
|
|
11845
|
-
execFile: (file, args) =>
|
|
11916
|
+
execFile: (file, args) => executeFile(file, args, active.env, platform),
|
|
11846
11917
|
resolveExecutable: (file) => resolveExecutable(file, active.env, platform)
|
|
11847
|
-
});
|
|
11918
|
+
}));
|
|
11848
11919
|
const packageManaged = [
|
|
11849
11920
|
"npm" /* Npm */,
|
|
11850
11921
|
"pnpm" /* Pnpm */,
|
|
11851
11922
|
"bun" /* Bun */,
|
|
11852
11923
|
"volta" /* Volta */
|
|
11853
11924
|
].includes(ownership.method);
|
|
11925
|
+
let detail = "The active Aident CLI owner could not be verified";
|
|
11926
|
+
if (ownership.method === "ephemeral" /* Ephemeral */) {
|
|
11927
|
+
detail = "An ephemeral Aident CLI cannot be used as the persistent global entrypoint";
|
|
11928
|
+
} else if (packageManaged) {
|
|
11929
|
+
if (nativePath) {
|
|
11930
|
+
detail = `The ${ownership.method}-managed Aident CLI is shadowing the installed native command; reinstall Aident to replace it`;
|
|
11931
|
+
} else if (current) {
|
|
11932
|
+
detail = `The Aident CLI is managed by ${ownership.method}`;
|
|
11933
|
+
} else {
|
|
11934
|
+
detail = `Run aident update --cli-only to update the active ${ownership.method}-managed CLI to v${requiredVersion} or newer`;
|
|
11935
|
+
}
|
|
11936
|
+
}
|
|
11937
|
+
if (ownership.method === "unknown" /* Unknown */ && ownershipTimedOut || versionTimedOut && !nativePath && ownership.method !== "ephemeral" /* Ephemeral */) {
|
|
11938
|
+
detail = PROBE_TIMEOUT_DETAIL;
|
|
11939
|
+
}
|
|
11854
11940
|
return {
|
|
11855
11941
|
ok: packageManaged && current && !nativePath,
|
|
11856
11942
|
owner: ownership.method,
|
|
11857
11943
|
...version ? { version } : {},
|
|
11858
11944
|
activePath: active.path,
|
|
11859
11945
|
...nativePath ? { nativePath } : {},
|
|
11860
|
-
detail
|
|
11946
|
+
detail
|
|
11861
11947
|
};
|
|
11862
11948
|
}
|
|
11863
|
-
async function resolveActiveAidentCommand(env, platform) {
|
|
11949
|
+
async function resolveActiveAidentCommand(env, platform, executeFile) {
|
|
11864
11950
|
if (platform === "win32") {
|
|
11865
|
-
const
|
|
11866
|
-
|
|
11867
|
-
|
|
11951
|
+
const command = "$ErrorActionPreference = 'Stop'; $env:Path = ([Environment]::GetEnvironmentVariable('Path', 'Machine'), [Environment]::GetEnvironmentVariable('Path', 'User') | Where-Object { $_ }) -join ';'; $active = Get-Command aident -CommandType Application -ErrorAction SilentlyContinue | Select-Object -First 1; $json = @{ path = $active.Source; pathValue = $env:Path } | ConvertTo-Json -Compress; [regex]::Replace($json, '[^\\x00-\\x7F]', { param($match) '\\u{0:x4}' -f [int][char]$match.Value })";
|
|
11952
|
+
try {
|
|
11953
|
+
const output = await executeFile(win323.join(env.SystemRoot ?? "C:\\Windows", "System32", "WindowsPowerShell", "v1.0", "powershell.exe"), ["-NoProfile", "-NonInteractive", "-Command", command], env, platform);
|
|
11954
|
+
const resolved = JSON.parse(output.stdout);
|
|
11955
|
+
if (!resolved || typeof resolved.path !== "string" || !win323.isAbsolute(resolved.path) || typeof resolved.pathValue !== "string") {
|
|
11956
|
+
return null;
|
|
11957
|
+
}
|
|
11958
|
+
const inherited = Object.fromEntries(Object.entries(env).filter(([key]) => key.toLowerCase() !== "path"));
|
|
11959
|
+
return { path: resolved.path, env: { ...inherited, PATH: resolved.pathValue } };
|
|
11960
|
+
} catch (error) {
|
|
11961
|
+
if (error instanceof Error && error.name === "TimeoutError")
|
|
11962
|
+
return null;
|
|
11963
|
+
const output = await executeFile(win323.join(env.SystemRoot ?? "C:\\Windows", "System32", "where.exe"), ["aident"], env, platform).catch(() => null);
|
|
11964
|
+
const path = output?.stdout.split(/\r?\n/).find((line) => win323.isAbsolute(line.trim()))?.trim();
|
|
11965
|
+
return path ? { path, env } : null;
|
|
11966
|
+
}
|
|
11868
11967
|
}
|
|
11869
11968
|
const shell = env.SHELL && isAbsolute5(env.SHELL) ? env.SHELL : "/bin/sh";
|
|
11870
11969
|
if (!SUPPORTED_SHELLS.has(basename3(shell)))
|
|
11871
11970
|
return resolveFromPath(env, platform);
|
|
11872
11971
|
const marker = "__AIDENT_ENTRYPOINT__";
|
|
11873
11972
|
const command = `printf '${marker}%s\\n${marker}%s\\n' "$PATH" "$(command -v aident 2>/dev/null || true)"`;
|
|
11874
|
-
const output = await
|
|
11973
|
+
const output = await executeFile(shell, ["-lic", command], env, platform).catch(() => null);
|
|
11875
11974
|
if (!output)
|
|
11876
11975
|
return resolveFromPath(env, platform);
|
|
11877
11976
|
const marked = output.stdout.split(/\r?\n/).filter((line) => line.startsWith(marker)).map((line) => line.slice(marker.length));
|
|
@@ -11902,12 +12001,66 @@ async function resolveExecutable(file, env, platform) {
|
|
|
11902
12001
|
async function isExecutable2(path, platform) {
|
|
11903
12002
|
return access2(path, platform === "win32" ? constants3.F_OK : constants3.X_OK).then(() => true, () => false);
|
|
11904
12003
|
}
|
|
11905
|
-
async function readAidentCliVersion(path, env) {
|
|
11906
|
-
const result = await
|
|
12004
|
+
async function readAidentCliVersion(path, env, platform, executeFile) {
|
|
12005
|
+
const result = await executeFile(path, ["--version"], env, platform).catch(() => null);
|
|
11907
12006
|
return result ? parseCliVersionOutput(result.stdout) : null;
|
|
11908
12007
|
}
|
|
11909
|
-
function runFile(file, args, env) {
|
|
11910
|
-
|
|
12008
|
+
async function runFile(file, args, env, platform, signal, timeout, spawnProbe = execFileCallback2) {
|
|
12009
|
+
const invocation = getPlatformExecFileInvocation(file, args, platform, env.ComSpec);
|
|
12010
|
+
if (platform !== "win32" || !timeout) {
|
|
12011
|
+
const { stdout, stderr } = await execFile3(invocation.file, invocation.args, { env, windowsHide: true });
|
|
12012
|
+
return { stdout, stderr };
|
|
12013
|
+
}
|
|
12014
|
+
signal?.throwIfAborted();
|
|
12015
|
+
return new Promise((resolve, reject) => {
|
|
12016
|
+
let cancelled = false;
|
|
12017
|
+
let completed = false;
|
|
12018
|
+
const child = spawnProbe(invocation.file, invocation.args, { env, windowsHide: true, encoding: "utf8" }, (error, stdout, stderr) => {
|
|
12019
|
+
completed = true;
|
|
12020
|
+
if (cancelled)
|
|
12021
|
+
return;
|
|
12022
|
+
clearTimeout(timer);
|
|
12023
|
+
signal?.removeEventListener("abort", cancel);
|
|
12024
|
+
if (error)
|
|
12025
|
+
reject(error);
|
|
12026
|
+
else
|
|
12027
|
+
resolve({ stdout, stderr });
|
|
12028
|
+
});
|
|
12029
|
+
const cancel = () => {
|
|
12030
|
+
if (cancelled)
|
|
12031
|
+
return;
|
|
12032
|
+
cancelled = true;
|
|
12033
|
+
clearTimeout(timer);
|
|
12034
|
+
signal?.removeEventListener("abort", cancel);
|
|
12035
|
+
let finished = false;
|
|
12036
|
+
const finish = () => {
|
|
12037
|
+
if (finished)
|
|
12038
|
+
return;
|
|
12039
|
+
finished = true;
|
|
12040
|
+
clearTimeout(cleanupTimer);
|
|
12041
|
+
child.removeListener("close", finish);
|
|
12042
|
+
child.kill();
|
|
12043
|
+
child.stdout?.destroy();
|
|
12044
|
+
child.stderr?.destroy();
|
|
12045
|
+
reject(new DOMException("Windows CLI entrypoint probe timed out", "TimeoutError"));
|
|
12046
|
+
};
|
|
12047
|
+
const cleanupTimeout = Math.min(timeout, WINDOWS_PROBE_CLEANUP_TIMEOUT_MS);
|
|
12048
|
+
const cleanupTimer = setTimeout(finish, cleanupTimeout);
|
|
12049
|
+
if (child.pid) {
|
|
12050
|
+
spawnProbe(win323.join(env.SystemRoot ?? "C:\\Windows", "System32", "taskkill.exe"), ["/PID", String(child.pid), "/T", "/F"], { windowsHide: true, timeout: cleanupTimeout, encoding: "utf8" }, () => {
|
|
12051
|
+
child.kill();
|
|
12052
|
+
if (completed)
|
|
12053
|
+
finish();
|
|
12054
|
+
else
|
|
12055
|
+
child.once("close", finish);
|
|
12056
|
+
});
|
|
12057
|
+
} else {
|
|
12058
|
+
finish();
|
|
12059
|
+
}
|
|
12060
|
+
};
|
|
12061
|
+
const timer = setTimeout(cancel, timeout);
|
|
12062
|
+
signal?.addEventListener("abort", cancel, { once: true });
|
|
12063
|
+
});
|
|
11911
12064
|
}
|
|
11912
12065
|
|
|
11913
12066
|
// src/harnesses/registry.ts
|
|
@@ -14632,7 +14785,8 @@ var HttpOperationPollingResultDefinitionSchema = objectType({
|
|
|
14632
14785
|
path: stringType().startsWith("/"),
|
|
14633
14786
|
idField: stringType().min(1),
|
|
14634
14787
|
idPathParam: stringType().min(1).optional(),
|
|
14635
|
-
idQueryParam: stringType().min(1).optional()
|
|
14788
|
+
idQueryParam: stringType().min(1).optional(),
|
|
14789
|
+
inputPathParams: arrayType(stringType().min(1)).optional()
|
|
14636
14790
|
}).superRefine((result, ctx) => {
|
|
14637
14791
|
if (result.idPathParam === undefined === (result.idQueryParam === undefined)) {
|
|
14638
14792
|
ctx.addIssue({
|
|
@@ -14647,16 +14801,28 @@ var HttpOperationPollingResultDefinitionSchema = objectType({
|
|
|
14647
14801
|
path: ["path"]
|
|
14648
14802
|
});
|
|
14649
14803
|
}
|
|
14804
|
+
for (const inputPathParam of result.inputPathParams ?? []) {
|
|
14805
|
+
if (!result.path.includes(`{${inputPathParam}}`)) {
|
|
14806
|
+
ctx.addIssue({
|
|
14807
|
+
code: ZodIssueCode.custom,
|
|
14808
|
+
message: "Polling result path must include every input path parameter",
|
|
14809
|
+
path: ["inputPathParams"]
|
|
14810
|
+
});
|
|
14811
|
+
}
|
|
14812
|
+
}
|
|
14650
14813
|
});
|
|
14651
14814
|
var HttpOperationPollingDefinitionSchema = objectType({
|
|
14652
14815
|
path: stringType().startsWith("/"),
|
|
14653
14816
|
taskIdField: stringType().min(1),
|
|
14654
14817
|
taskIdPathParam: stringType().min(1).optional(),
|
|
14655
14818
|
taskIdQueryParam: stringType().min(1).optional(),
|
|
14656
|
-
|
|
14657
|
-
|
|
14658
|
-
|
|
14819
|
+
inputPathParams: arrayType(stringType().min(1)).optional(),
|
|
14820
|
+
statusField: stringType().min(1).optional(),
|
|
14821
|
+
pendingStatuses: arrayType(stringType().min(1)).min(1).optional(),
|
|
14822
|
+
terminalStatuses: arrayType(stringType().min(1)).min(1).optional(),
|
|
14659
14823
|
failureStatuses: arrayType(stringType().min(1)).optional(),
|
|
14824
|
+
successField: stringType().min(1).optional(),
|
|
14825
|
+
failureField: stringType().min(1).optional(),
|
|
14660
14826
|
intervalMs: numberType().int().min(HTTP_OPERATION_MIN_POLL_INTERVAL_MS),
|
|
14661
14827
|
timeoutMs: numberType().int().min(HTTP_OPERATION_MIN_TIMEOUT_MS).max(HTTP_OPERATION_MAX_TIMEOUT_MS),
|
|
14662
14828
|
result: HttpOperationPollingResultDefinitionSchema.optional()
|
|
@@ -14674,7 +14840,38 @@ var HttpOperationPollingDefinitionSchema = objectType({
|
|
|
14674
14840
|
path: ["path"]
|
|
14675
14841
|
});
|
|
14676
14842
|
}
|
|
14677
|
-
const
|
|
14843
|
+
for (const inputPathParam of polling.inputPathParams ?? []) {
|
|
14844
|
+
if (!polling.path.includes(`{${inputPathParam}}`)) {
|
|
14845
|
+
ctx.addIssue({
|
|
14846
|
+
code: ZodIssueCode.custom,
|
|
14847
|
+
message: "Polling path must include every input path parameter",
|
|
14848
|
+
path: ["inputPathParams"]
|
|
14849
|
+
});
|
|
14850
|
+
}
|
|
14851
|
+
}
|
|
14852
|
+
const usesStatus = polling.statusField !== undefined;
|
|
14853
|
+
const usesFields = polling.successField !== undefined || polling.failureField !== undefined;
|
|
14854
|
+
if (usesStatus === usesFields) {
|
|
14855
|
+
ctx.addIssue({
|
|
14856
|
+
code: ZodIssueCode.custom,
|
|
14857
|
+
message: "Polling must define either status fields or success and failure fields"
|
|
14858
|
+
});
|
|
14859
|
+
}
|
|
14860
|
+
if (usesStatus && (!polling.pendingStatuses || !polling.terminalStatuses)) {
|
|
14861
|
+
ctx.addIssue({
|
|
14862
|
+
code: ZodIssueCode.custom,
|
|
14863
|
+
message: "Status polling requires pending and terminal statuses",
|
|
14864
|
+
path: ["statusField"]
|
|
14865
|
+
});
|
|
14866
|
+
}
|
|
14867
|
+
if (usesFields && (!polling.successField || !polling.failureField)) {
|
|
14868
|
+
ctx.addIssue({
|
|
14869
|
+
code: ZodIssueCode.custom,
|
|
14870
|
+
message: "Field polling requires success and failure fields",
|
|
14871
|
+
path: ["successField"]
|
|
14872
|
+
});
|
|
14873
|
+
}
|
|
14874
|
+
const terminalStatuses = new Set(polling.terminalStatuses ?? []);
|
|
14678
14875
|
if (polling.failureStatuses?.some((status) => !terminalStatuses.has(status))) {
|
|
14679
14876
|
ctx.addIssue({
|
|
14680
14877
|
code: ZodIssueCode.custom,
|
|
@@ -16977,6 +17174,10 @@ var LOADOUT_ONBOARDING_GUIDE_MESSAGES = {
|
|
|
16977
17174
|
completedTitle: "Run another task",
|
|
16978
17175
|
description: "Choose your AI app, then enter a task.",
|
|
16979
17176
|
exploreDescription: `Use ${LOADOUT_APPS_LABEL} for research, content, video, and more.`,
|
|
17177
|
+
hostedAction: "Try the hosted agent",
|
|
17178
|
+
hostedDescription: "Run a real task on your phone. No agent installation needed.",
|
|
17179
|
+
hostedTitle: "Try Loadout on your phone",
|
|
17180
|
+
returnToHostedResult: "Return to your hosted result",
|
|
16980
17181
|
placeholder: "Enter a task...",
|
|
16981
17182
|
title: "Run a task with Loadout",
|
|
16982
17183
|
tryTool: `Explore ready-to-use ${LOADOUT_APPS_LABEL}`
|
|
@@ -17034,6 +17235,10 @@ var LOADOUT_ONBOARDING_GUIDE_MESSAGES = {
|
|
|
17034
17235
|
completedTitle: "再运行一个任务",
|
|
17035
17236
|
description: "选择你的 AI 应用,然后输入任务。",
|
|
17036
17237
|
exploreDescription: `使用${chineseTerminology.apps}完成研究、内容、视频等任务。`,
|
|
17238
|
+
hostedAction: "试用托管智能体",
|
|
17239
|
+
hostedDescription: "在手机上运行真实任务,无需安装智能体。",
|
|
17240
|
+
hostedTitle: "在手机上试用 Loadout",
|
|
17241
|
+
returnToHostedResult: "返回托管任务结果",
|
|
17037
17242
|
placeholder: "输入任务…",
|
|
17038
17243
|
title: "使用 Loadout 运行任务",
|
|
17039
17244
|
tryTool: `探索即开即用的${chineseTerminology.apps}`
|
|
@@ -17091,6 +17296,10 @@ var LOADOUT_ONBOARDING_GUIDE_MESSAGES = {
|
|
|
17091
17296
|
completedTitle: "Ejecuta otra tarea",
|
|
17092
17297
|
description: "Elige tu app de IA e introduce una tarea.",
|
|
17093
17298
|
exploreDescription: `Usa ${LOADOUT_APPS_LABEL} para investigación, contenido, video y más.`,
|
|
17299
|
+
hostedAction: "Probar el agente alojado",
|
|
17300
|
+
hostedDescription: "Ejecuta una tarea real en tu móvil sin instalar nada en un agente.",
|
|
17301
|
+
hostedTitle: "Prueba Loadout en tu móvil",
|
|
17302
|
+
returnToHostedResult: "Volver al resultado del agente",
|
|
17094
17303
|
placeholder: "Introduce una tarea...",
|
|
17095
17304
|
title: "Ejecuta una tarea con Loadout",
|
|
17096
17305
|
tryTool: `Explora ${LOADOUT_APPS_LABEL} listas para usar`
|
|
@@ -17148,6 +17357,10 @@ var LOADOUT_ONBOARDING_GUIDE_MESSAGES = {
|
|
|
17148
17357
|
completedTitle: "Exécuter une autre tâche",
|
|
17149
17358
|
description: "Choisissez votre app IA, puis saisissez une tâche.",
|
|
17150
17359
|
exploreDescription: `Utilisez des ${LOADOUT_APPS_LABEL} pour la recherche, le contenu, la vidéo et plus encore.`,
|
|
17360
|
+
hostedAction: "Essayer l’agent hébergé",
|
|
17361
|
+
hostedDescription: "Exécutez une vraie tâche sur votre téléphone, sans installer d’agent.",
|
|
17362
|
+
hostedTitle: "Essayez Loadout sur votre téléphone",
|
|
17363
|
+
returnToHostedResult: "Revenir au résultat de l’agent",
|
|
17151
17364
|
placeholder: "Saisissez une tâche...",
|
|
17152
17365
|
title: "Exécuter une tâche avec Loadout",
|
|
17153
17366
|
tryTool: `Explorer les ${LOADOUT_APPS_LABEL} prêtes à l’emploi`
|
|
@@ -17205,6 +17418,10 @@ var LOADOUT_ONBOARDING_GUIDE_MESSAGES = {
|
|
|
17205
17418
|
completedTitle: "別のタスクを実行",
|
|
17206
17419
|
description: "AIアプリを選び、タスクを入力します。",
|
|
17207
17420
|
exploreDescription: `リサーチ、コンテンツ、動画などに${LOADOUT_APPS_LABEL}を活用できます。`,
|
|
17421
|
+
hostedAction: "ホスト型エージェントを試す",
|
|
17422
|
+
hostedDescription: "エージェントをインストールせずに、スマートフォンで実際のタスクを実行できます。",
|
|
17423
|
+
hostedTitle: "スマートフォンでLoadoutを試す",
|
|
17424
|
+
returnToHostedResult: "ホスト型エージェントの結果に戻る",
|
|
17208
17425
|
placeholder: "タスクを入力...",
|
|
17209
17426
|
title: "Loadoutでタスクを実行",
|
|
17210
17427
|
tryTool: `すぐに使える${LOADOUT_APPS_LABEL}を探す`
|
|
@@ -17262,6 +17479,10 @@ var LOADOUT_ONBOARDING_GUIDE_MESSAGES = {
|
|
|
17262
17479
|
completedTitle: "एक और टास्क चलाएं",
|
|
17263
17480
|
description: "अपना AI ऐप चुनें, फिर एक टास्क दर्ज करें।",
|
|
17264
17481
|
exploreDescription: `रिसर्च, कंटेंट, वीडियो और अन्य काम के लिए ${LOADOUT_APPS_LABEL} इस्तेमाल करें।`,
|
|
17482
|
+
hostedAction: "होस्टेड एजेंट आज़माएं",
|
|
17483
|
+
hostedDescription: "बिना एजेंट इंस्टॉल किए फ़ोन पर असली टास्क चलाएं।",
|
|
17484
|
+
hostedTitle: "फ़ोन पर Loadout आज़माएं",
|
|
17485
|
+
returnToHostedResult: "होस्टेड परिणाम पर वापस जाएं",
|
|
17265
17486
|
placeholder: "टास्क दर्ज करें...",
|
|
17266
17487
|
title: "Loadout से टास्क चलाएं",
|
|
17267
17488
|
tryTool: `तैयार ${LOADOUT_APPS_LABEL} देखें`
|
|
@@ -18683,7 +18904,7 @@ async function stageOnboardingSkill(home, artifact) {
|
|
|
18683
18904
|
|
|
18684
18905
|
// src/onboarding/transaction.ts
|
|
18685
18906
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
18686
|
-
import { cp, lstat as lstat11, mkdir as mkdir12, readdir as readdir6, readFile as readFile17, rename as rename8, rm as rm7, symlink as symlink5 } from "node:fs/promises";
|
|
18907
|
+
import { cp as cp2, lstat as lstat11, mkdir as mkdir12, readdir as readdir6, readFile as readFile17, rename as rename8, rm as rm7, symlink as symlink5 } from "node:fs/promises";
|
|
18687
18908
|
import { dirname as dirname11, join as join16, relative as relative5 } from "node:path";
|
|
18688
18909
|
async function applyOnboardingPlan(plan, options) {
|
|
18689
18910
|
if (options.confirmationDigest !== plan.confirmationDigest)
|
|
@@ -18851,7 +19072,7 @@ async function applyChange(change, desiredContent, options) {
|
|
|
18851
19072
|
if (change.action === "copy" /* Copy */) {
|
|
18852
19073
|
const temporary = `${change.target}.${randomUUID8()}.tmp`;
|
|
18853
19074
|
await mkdir12(dirname11(temporary), { recursive: true, mode: 448 });
|
|
18854
|
-
await
|
|
19075
|
+
await cp2(options.skillSourceDirectory, temporary, { recursive: true, errorOnExist: true });
|
|
18855
19076
|
await rename8(temporary, change.target);
|
|
18856
19077
|
return;
|
|
18857
19078
|
}
|
|
@@ -19002,7 +19223,7 @@ class OnboardingService {
|
|
|
19002
19223
|
}
|
|
19003
19224
|
}
|
|
19004
19225
|
|
|
19005
|
-
// ../web/shared/loadout/
|
|
19226
|
+
// ../web/shared/loadout/LoadoutOnboardingTelemetryContract.ts
|
|
19006
19227
|
var LoadoutOnboardingPath;
|
|
19007
19228
|
((LoadoutOnboardingPath) => {
|
|
19008
19229
|
LoadoutOnboardingPath["Unselected"] = "unselected";
|
|
@@ -19019,6 +19240,8 @@ var LoadoutOnboardingTelemetryStage;
|
|
|
19019
19240
|
LoadoutOnboardingTelemetryStage["LoginCompleted"] = "login_completed";
|
|
19020
19241
|
LoadoutOnboardingTelemetryStage["MethodSelected"] = "method_selected";
|
|
19021
19242
|
LoadoutOnboardingTelemetryStage["NativeDownloadStarted"] = "native_download_started";
|
|
19243
|
+
LoadoutOnboardingTelemetryStage["PackageInstallStarted"] = "package_install_started";
|
|
19244
|
+
LoadoutOnboardingTelemetryStage["PackageInstallCompleted"] = "package_install_completed";
|
|
19022
19245
|
LoadoutOnboardingTelemetryStage["DesktopStarted"] = "desktop_started";
|
|
19023
19246
|
LoadoutOnboardingTelemetryStage["InstallationCompleted"] = "installation_completed";
|
|
19024
19247
|
LoadoutOnboardingTelemetryStage["OnboardingStarted"] = "onboarding_started";
|
|
@@ -19055,6 +19278,8 @@ var LoadoutOnboardingLaunchSource;
|
|
|
19055
19278
|
LoadoutOnboardingLaunchSource["Desktop"] = "desktop";
|
|
19056
19279
|
LoadoutOnboardingLaunchSource["Web"] = "web";
|
|
19057
19280
|
})(LoadoutOnboardingLaunchSource ||= {});
|
|
19281
|
+
|
|
19282
|
+
// ../web/shared/loadout/LoadoutOnboardingTelemetry.ts
|
|
19058
19283
|
var LoadoutOnboardingClientFamily;
|
|
19059
19284
|
((LoadoutOnboardingClientFamily) => {
|
|
19060
19285
|
LoadoutOnboardingClientFamily["Aident"] = "aident";
|
|
@@ -19168,6 +19393,8 @@ function recordLoadoutOnboardingTelemetry(baseUrl, event, fetchImpl = fetch) {
|
|
|
19168
19393
|
genRecordLoadoutOnboardingTelemetry(baseUrl, event, fetchImpl);
|
|
19169
19394
|
}
|
|
19170
19395
|
async function genRecordLoadoutOnboardingTelemetry(baseUrl, event, fetchImpl = fetch) {
|
|
19396
|
+
if (process.env.AIDENT_DISABLE_ONBOARDING_TELEMETRY === "1")
|
|
19397
|
+
return false;
|
|
19171
19398
|
const endpoint = `${baseUrl.replace(/\/+$/, "")}/.well-known/aident-onboarding-event`;
|
|
19172
19399
|
if (!isTrustedAidentMetadataUrl(endpoint))
|
|
19173
19400
|
return false;
|
|
@@ -19204,11 +19431,22 @@ var UI_FILES = ["index.html", "app.js", "style.css"];
|
|
|
19204
19431
|
var MAX_UI_BYTES = 5 * 1024 * 1024;
|
|
19205
19432
|
async function resolveOnboardingUiAssets(baseUrl, cliVersion, home) {
|
|
19206
19433
|
const cacheRoot = join17(home, ".aident", "ui");
|
|
19207
|
-
|
|
19434
|
+
const controller = new AbortController;
|
|
19435
|
+
const fallback = new Promise((resolve) => {
|
|
19436
|
+
controller.signal.addEventListener("abort", () => resolve(null), { once: true });
|
|
19437
|
+
});
|
|
19438
|
+
const timeout = setTimeout(() => controller.abort(), 2000);
|
|
19439
|
+
timeout.unref();
|
|
19440
|
+
try {
|
|
19441
|
+
return await Promise.race([resolveOnlineOrCached(baseUrl, cliVersion, cacheRoot, controller.signal), fallback]);
|
|
19442
|
+
} finally {
|
|
19443
|
+
clearTimeout(timeout);
|
|
19444
|
+
controller.abort();
|
|
19445
|
+
}
|
|
19208
19446
|
}
|
|
19209
|
-
async function resolveOnlineOrCached(baseUrl, cliVersion, cacheRoot) {
|
|
19447
|
+
async function resolveOnlineOrCached(baseUrl, cliVersion, cacheRoot, signal) {
|
|
19210
19448
|
try {
|
|
19211
|
-
const metadata = await fetchLoadoutSkillMetadata(baseUrl);
|
|
19449
|
+
const metadata = await fetchLoadoutSkillMetadata(baseUrl, signal);
|
|
19212
19450
|
const policy = metadata?.updatePolicy;
|
|
19213
19451
|
const descriptor = policy?.schemaVersion === 2 ? policy.onboardingUi : undefined;
|
|
19214
19452
|
if (!descriptor || !isCompatible(descriptor, cliVersion))
|
|
@@ -19216,7 +19454,7 @@ async function resolveOnlineOrCached(baseUrl, cliVersion, cacheRoot) {
|
|
|
19216
19454
|
if (!isTrustedAidentMetadataUrl(descriptor.url) || new URL(descriptor.url).origin !== new URL(baseUrl).origin) {
|
|
19217
19455
|
return loadCachedUi(cacheRoot, cliVersion);
|
|
19218
19456
|
}
|
|
19219
|
-
const response = await fetch(descriptor.url, { redirect: "error" });
|
|
19457
|
+
const response = await fetch(descriptor.url, { redirect: "error", signal });
|
|
19220
19458
|
if (!response.ok)
|
|
19221
19459
|
return loadCachedUi(cacheRoot, cliVersion);
|
|
19222
19460
|
const bytes = await readBoundedResponseBody(response, descriptor.byteLength, MAX_UI_BYTES, "onboarding-ui-response-too-large");
|
|
@@ -19229,12 +19467,6 @@ async function resolveOnlineOrCached(baseUrl, cliVersion, cacheRoot) {
|
|
|
19229
19467
|
return loadCachedUi(cacheRoot, cliVersion);
|
|
19230
19468
|
}
|
|
19231
19469
|
}
|
|
19232
|
-
function resolveTimeout(milliseconds) {
|
|
19233
|
-
return new Promise((resolve) => {
|
|
19234
|
-
const timer = setTimeout(() => resolve(null), milliseconds);
|
|
19235
|
-
timer.unref();
|
|
19236
|
-
});
|
|
19237
|
-
}
|
|
19238
19470
|
function verifyArtifact(bytes, descriptor) {
|
|
19239
19471
|
return descriptor.byteLength <= MAX_UI_BYTES && bytes.byteLength === descriptor.byteLength && createHash11("sha256").update(bytes).digest("hex") === descriptor.sha256 && verifyMinisign(bytes, descriptor.signature, descriptor.signingKeyId);
|
|
19240
19472
|
}
|