@notis_ai/cli 0.2.0-beta.154.1 → 0.2.0-beta.156.1
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/agent-hooks/notis-agent-hook.mjs +209 -110
- package/dist/base-skills/notis-apps/SKILL.md +33 -30
- package/dist/skill-sync/index.js +134 -72
- package/dist/skill-sync/index.js.map +2 -2
- package/package.json +1 -1
- package/src/command-specs/apps.js +4 -2
- package/src/command-specs/skills.js +3 -2
- package/src/command-specs/tools.js +5 -0
- package/src/runtime/app-dev-build-supervisor.js +47 -0
- package/src/runtime/app-dev-build.js +41 -0
- package/src/runtime/app-dev-server.js +2 -6
- package/src/runtime/skill-sync/cloud-client.ts +5 -3
- package/src/runtime/skill-sync/index.ts +73 -65
- package/src/runtime/skill-sync/symlink-manager.ts +66 -16
- package/src/runtime/skill-sync/types.ts +5 -0
- package/template/app/page.tsx +8 -7
- package/template/packages/sdk/src/components/MultiSelectActionBar.tsx +49 -8
- package/template/packages/sdk/src/components/Skeleton.tsx +24 -0
- package/template/packages/sdk/src/hooks/useCloudComputer.ts +15 -48
- package/template/packages/sdk/src/hooks/useDatabaseSchema.ts +17 -53
- package/template/packages/sdk/src/hooks/useDatabaseSubscription.ts +2 -2
- package/template/packages/sdk/src/hooks/useDocument.ts +12 -47
- package/template/packages/sdk/src/hooks/useDocuments.ts +18 -58
- package/template/packages/sdk/src/hooks/useQuery.ts +71 -0
- package/template/packages/sdk/src/hooks/useToolQuery.ts +12 -0
- package/template/packages/sdk/src/hooks/useTopBarSearch.ts +15 -7
- package/template/packages/sdk/src/index.ts +8 -0
- package/template/packages/sdk/src/interactions/shortcuts.tsx +1 -1
- package/template/packages/sdk/src/queryCache.ts +162 -0
- package/template/packages/sdk/src/runtime.ts +5 -0
|
@@ -979,7 +979,7 @@ var require_suggestSimilar = __commonJS({
|
|
|
979
979
|
// node_modules/commander/lib/command.js
|
|
980
980
|
var require_command = __commonJS({
|
|
981
981
|
"node_modules/commander/lib/command.js"(exports) {
|
|
982
|
-
var
|
|
982
|
+
var EventEmitter2 = __require("node:events").EventEmitter;
|
|
983
983
|
var childProcess = __require("node:child_process");
|
|
984
984
|
var path3 = __require("node:path");
|
|
985
985
|
var fs3 = __require("node:fs");
|
|
@@ -989,7 +989,7 @@ var require_command = __commonJS({
|
|
|
989
989
|
var { Help: Help2 } = require_help();
|
|
990
990
|
var { Option: Option2, DualOptions } = require_option();
|
|
991
991
|
var { suggestSimilar } = require_suggestSimilar();
|
|
992
|
-
var Command2 = class _Command extends
|
|
992
|
+
var Command2 = class _Command extends EventEmitter2 {
|
|
993
993
|
/**
|
|
994
994
|
* Initialize a new `Command`.
|
|
995
995
|
*
|
|
@@ -3796,15 +3796,22 @@ async function downloadSkillBundle(bundleUrl) {
|
|
|
3796
3796
|
}
|
|
3797
3797
|
return Buffer.from(await response.arrayBuffer());
|
|
3798
3798
|
}
|
|
3799
|
-
async function updateAgentTargets(serverUrl, jwt, skillId, targets) {
|
|
3799
|
+
async function updateAgentTargets(serverUrl, jwt, skillId, targets, expectedUpdatedAt) {
|
|
3800
3800
|
return requestJson(`${serverUrl}/portal_skills/agent-targets`, jwt, {
|
|
3801
3801
|
method: "PATCH",
|
|
3802
3802
|
body: {
|
|
3803
3803
|
skill_id: skillId,
|
|
3804
|
-
agent_targets: targets
|
|
3804
|
+
agent_targets: targets,
|
|
3805
|
+
...expectedUpdatedAt ? { expected_updated_at: expectedUpdatedAt } : {}
|
|
3805
3806
|
}
|
|
3806
3807
|
});
|
|
3807
3808
|
}
|
|
3809
|
+
function agentFailureLabel(agent) {
|
|
3810
|
+
return AGENT_FAILURE_LABELS[agent] ?? agent;
|
|
3811
|
+
}
|
|
3812
|
+
function agentFolderFailureName(agent) {
|
|
3813
|
+
return `${agentFailureLabel(agent)} skills folder`;
|
|
3814
|
+
}
|
|
3808
3815
|
async function removeForeignAccountSymlinks(skillsDir, options = {}) {
|
|
3809
3816
|
const agentSkillDirs = { ...defaultAgentSkillDirs(skillsDir), ...options.agentSkillDirs };
|
|
3810
3817
|
const currentRoot = path2.resolve(skillsDir);
|
|
@@ -3865,8 +3872,9 @@ async function isManagedSymlink(linkPath, managedRoots) {
|
|
|
3865
3872
|
const target = await fs2.readlink(linkPath);
|
|
3866
3873
|
const resolvedTarget = path2.resolve(path2.dirname(linkPath), target);
|
|
3867
3874
|
return managedRoots.some((root) => resolvedTarget === root || resolvedTarget.startsWith(`${root}${path2.sep}`));
|
|
3868
|
-
} catch {
|
|
3869
|
-
return false;
|
|
3875
|
+
} catch (error) {
|
|
3876
|
+
if (error?.code === "ENOENT") return false;
|
|
3877
|
+
throw error;
|
|
3870
3878
|
}
|
|
3871
3879
|
}
|
|
3872
3880
|
async function ensureCorrectSymlink(linkPath, targetPath) {
|
|
@@ -3882,7 +3890,8 @@ async function ensureCorrectSymlink(linkPath, targetPath) {
|
|
|
3882
3890
|
} else {
|
|
3883
3891
|
return "blocked";
|
|
3884
3892
|
}
|
|
3885
|
-
} catch {
|
|
3893
|
+
} catch (error) {
|
|
3894
|
+
if (error?.code !== "ENOENT") throw error;
|
|
3886
3895
|
}
|
|
3887
3896
|
const relativePath = path2.relative(path2.dirname(linkPath), targetPath);
|
|
3888
3897
|
await fs2.symlink(relativePath, linkPath);
|
|
@@ -3894,19 +3903,26 @@ function defaultAgentSkillDirs(skillsDir) {
|
|
|
3894
3903
|
...EXTERNAL_AGENT_SKILL_DIRS
|
|
3895
3904
|
};
|
|
3896
3905
|
}
|
|
3897
|
-
async function removeUndesiredManagedSymlinks(agentDir, desiredSkills, managedRoots) {
|
|
3906
|
+
async function removeUndesiredManagedSymlinks(agentDir, desiredSkills, managedRoots, failures, agent) {
|
|
3898
3907
|
let removed = 0;
|
|
3899
3908
|
try {
|
|
3900
3909
|
await fs2.mkdir(agentDir, { recursive: true });
|
|
3901
3910
|
const existingEntries = await fs2.readdir(agentDir, { withFileTypes: true });
|
|
3902
3911
|
for (const entry of existingEntries) {
|
|
3903
3912
|
const entryPath = path2.join(agentDir, entry.name);
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3913
|
+
try {
|
|
3914
|
+
if (!desiredSkills.has(entry.name) && await isManagedSymlink(entryPath, managedRoots)) {
|
|
3915
|
+
await fs2.unlink(entryPath);
|
|
3916
|
+
removed += 1;
|
|
3917
|
+
}
|
|
3918
|
+
} catch (error) {
|
|
3919
|
+
if (error?.code !== "ENOENT") {
|
|
3920
|
+
failures.push({ name: entry.name, error: `${agentFailureLabel(agent)}: could not remove skill link (${error.message})` });
|
|
3921
|
+
}
|
|
3907
3922
|
}
|
|
3908
3923
|
}
|
|
3909
|
-
} catch {
|
|
3924
|
+
} catch (error) {
|
|
3925
|
+
failures.push({ name: agentFolderFailureName(agent), error: `Could not read agent skills directory (${error.message})` });
|
|
3910
3926
|
}
|
|
3911
3927
|
return removed;
|
|
3912
3928
|
}
|
|
@@ -3951,7 +3967,7 @@ async function detectDeletedAgentSymlinks(cloudSkills, previousState, skillsDir
|
|
|
3951
3967
|
continue;
|
|
3952
3968
|
}
|
|
3953
3969
|
const previous = previousState.skills[skill.name];
|
|
3954
|
-
if (!previous) {
|
|
3970
|
+
if (!previous || previous.cloudId !== skill.id || previous.verifiedAgentLinks?.[agent] !== true || !skill.updated_at || previous.cloudUpdatedAt !== skill.updated_at) {
|
|
3955
3971
|
continue;
|
|
3956
3972
|
}
|
|
3957
3973
|
const cloudTargets = normalizeAgentTargets(skill.agent_targets);
|
|
@@ -3982,7 +3998,9 @@ async function syncSymlinks(skills, skillsDir = LEGACY_AGENTS_SKILLS_DIR, option
|
|
|
3982
3998
|
const result = {
|
|
3983
3999
|
linked: 0,
|
|
3984
4000
|
removed: 0,
|
|
3985
|
-
skipped: 0
|
|
4001
|
+
skipped: 0,
|
|
4002
|
+
verifiedAgentLinks: {},
|
|
4003
|
+
failures: []
|
|
3986
4004
|
};
|
|
3987
4005
|
const agentSkillDirs = { ...defaultAgentSkillDirs(skillsDir), ...options.agentSkillDirs };
|
|
3988
4006
|
const legacyGlobalSkillsDir = options.legacyGlobalSkillsDir || LEGACY_AGENTS_SKILLS_DIR;
|
|
@@ -4017,21 +4035,34 @@ async function syncSymlinks(skills, skillsDir = LEGACY_AGENTS_SKILLS_DIR, option
|
|
|
4017
4035
|
result.skipped += desiredByAgent[agent].size;
|
|
4018
4036
|
continue;
|
|
4019
4037
|
}
|
|
4020
|
-
|
|
4038
|
+
try {
|
|
4039
|
+
await fs2.mkdir(agentDir, { recursive: true });
|
|
4040
|
+
} catch (error) {
|
|
4041
|
+
result.failures.push({ name: agentFolderFailureName(agent), error: `Could not create agent skills directory (${error.message})` });
|
|
4042
|
+
continue;
|
|
4043
|
+
}
|
|
4021
4044
|
const desiredSkills = desiredByAgent[agent];
|
|
4022
4045
|
if (options.removeUndesired !== false) {
|
|
4023
|
-
result.removed += await removeUndesiredManagedSymlinks(agentDir, desiredSkills, managedRoots);
|
|
4046
|
+
result.removed += await removeUndesiredManagedSymlinks(agentDir, desiredSkills, managedRoots, result.failures, agent);
|
|
4024
4047
|
}
|
|
4025
4048
|
for (const skillName of desiredSkills) {
|
|
4026
4049
|
const targetPath = path2.join(skillsDir, skillName);
|
|
4027
4050
|
const linkPath = path2.join(agentDir, safeName(skillName, agentDir));
|
|
4028
4051
|
try {
|
|
4029
|
-
await fs2.
|
|
4052
|
+
if (!(await fs2.stat(path2.join(targetPath, "SKILL.md"))).isFile()) throw new Error("Missing SKILL.md");
|
|
4030
4053
|
} catch {
|
|
4031
4054
|
result.skipped += 1;
|
|
4055
|
+
result.failures.push({ name: skillName, error: `${agentFailureLabel(agent)}: SKILL.md is missing or unreadable` });
|
|
4056
|
+
continue;
|
|
4057
|
+
}
|
|
4058
|
+
let syncOutcome;
|
|
4059
|
+
try {
|
|
4060
|
+
syncOutcome = await ensureCorrectSymlink(linkPath, targetPath);
|
|
4061
|
+
} catch (error) {
|
|
4062
|
+
result.skipped += 1;
|
|
4063
|
+
result.failures.push({ name: skillName, error: `${agentFailureLabel(agent)}: could not create skill link (${error.message})` });
|
|
4032
4064
|
continue;
|
|
4033
4065
|
}
|
|
4034
|
-
const syncOutcome = await ensureCorrectSymlink(linkPath, targetPath);
|
|
4035
4066
|
if (syncOutcome === "linked") {
|
|
4036
4067
|
result.linked += 1;
|
|
4037
4068
|
} else if (syncOutcome === "blocked") {
|
|
@@ -4039,9 +4070,13 @@ async function syncSymlinks(skills, skillsDir = LEGACY_AGENTS_SKILLS_DIR, option
|
|
|
4039
4070
|
`[skill-sync] Could not link "${skillName}" for ${agent}: non-symlink entry blocks ${linkPath}`
|
|
4040
4071
|
);
|
|
4041
4072
|
result.skipped += 1;
|
|
4073
|
+
result.failures.push({ name: skillName, error: `${agentFailureLabel(agent)}: an existing file or folder blocks the skill link` });
|
|
4042
4074
|
} else {
|
|
4043
4075
|
result.skipped += 1;
|
|
4044
4076
|
}
|
|
4077
|
+
if (syncOutcome !== "blocked") {
|
|
4078
|
+
result.verifiedAgentLinks[skillName] = { ...result.verifiedAgentLinks[skillName], [agent]: true };
|
|
4079
|
+
}
|
|
4045
4080
|
}
|
|
4046
4081
|
}
|
|
4047
4082
|
if (options.removeUndesired !== false && !Object.values(agentSkillDirs).some(
|
|
@@ -4050,7 +4085,9 @@ async function syncSymlinks(skills, skillsDir = LEGACY_AGENTS_SKILLS_DIR, option
|
|
|
4050
4085
|
result.removed += await removeUndesiredManagedSymlinks(
|
|
4051
4086
|
legacyGlobalSkillsDir,
|
|
4052
4087
|
/* @__PURE__ */ new Set(),
|
|
4053
|
-
managedRoots
|
|
4088
|
+
managedRoots,
|
|
4089
|
+
result.failures,
|
|
4090
|
+
"legacy"
|
|
4054
4091
|
);
|
|
4055
4092
|
}
|
|
4056
4093
|
return result;
|
|
@@ -4149,7 +4186,7 @@ function shouldWriteCloudSkill(cloudSkill, localSkills, previousState) {
|
|
|
4149
4186
|
const localChangedSinceLastSync = !previous || previous.folderHash !== localSkill.folderHash;
|
|
4150
4187
|
return !localChangedSinceLastSync && Boolean(cloudHash) && cloudHash !== localSkill.folderHash;
|
|
4151
4188
|
}
|
|
4152
|
-
function buildSyncState(pullResponse, localSkills, lastSyncedAt) {
|
|
4189
|
+
function buildSyncState(pullResponse, localSkills, lastSyncedAt, verifiedAgentLinks = {}) {
|
|
4153
4190
|
const localSkillMap = toSkillMap(localSkills);
|
|
4154
4191
|
const skills = Object.fromEntries(
|
|
4155
4192
|
pullResponse.skills.map((skill) => {
|
|
@@ -4160,6 +4197,8 @@ function buildSyncState(pullResponse, localSkills, lastSyncedAt) {
|
|
|
4160
4197
|
cloudId: skill.id,
|
|
4161
4198
|
folderHash: localSkill?.folderHash || skill.skill_folder_hash || "",
|
|
4162
4199
|
agentTargets: normalizeAgentTargets(skill.agent_targets),
|
|
4200
|
+
verifiedAgentLinks: skill.status === "active" ? verifiedAgentLinks[skill.name] ?? {} : {},
|
|
4201
|
+
cloudUpdatedAt: skill.updated_at,
|
|
4163
4202
|
syncedAt: lastSyncedAt || (/* @__PURE__ */ new Date()).toISOString()
|
|
4164
4203
|
}
|
|
4165
4204
|
];
|
|
@@ -4215,7 +4254,7 @@ function applyLegacyFirstRunState(localSkills, scopedState, legacyState) {
|
|
|
4215
4254
|
skills: migratedSkills
|
|
4216
4255
|
};
|
|
4217
4256
|
}
|
|
4218
|
-
async function writePulledSkillsToScopedMirror(pullResponse, localSkills, previousState, syncPaths, deps) {
|
|
4257
|
+
async function writePulledSkillsToScopedMirror(pullResponse, localSkills, previousState, syncPaths, deps, failures = []) {
|
|
4219
4258
|
const localSkillMap = toSkillMap(localSkills);
|
|
4220
4259
|
const warnSkillSync = (message, error) => {
|
|
4221
4260
|
console.warn(`[Notis] ${message}`, error);
|
|
@@ -4231,6 +4270,8 @@ async function writePulledSkillsToScopedMirror(pullResponse, localSkills, previo
|
|
|
4231
4270
|
onWarning: warnSkillSync
|
|
4232
4271
|
})) {
|
|
4233
4272
|
downloaded += 1;
|
|
4273
|
+
} else {
|
|
4274
|
+
failures.push({ name: cloudSkill.name, error: "Skill content could not be downloaded or written; sync will retry" });
|
|
4234
4275
|
}
|
|
4235
4276
|
}
|
|
4236
4277
|
return downloaded;
|
|
@@ -4258,25 +4299,42 @@ async function materializeCloudSkillsForLocalShell(serverUrl, jwt, dependencies
|
|
|
4258
4299
|
assertSkillsPullAuthorized(pullResponse);
|
|
4259
4300
|
const previousState = await deps.readSyncState(syncPaths);
|
|
4260
4301
|
const localSkills = await deps.scanLocalSkills(syncPaths);
|
|
4302
|
+
const failedDownloads = [];
|
|
4261
4303
|
const downloaded = await writePulledSkillsToScopedMirror(
|
|
4262
4304
|
pullResponse,
|
|
4263
4305
|
localSkills,
|
|
4264
4306
|
previousState,
|
|
4265
4307
|
syncPaths,
|
|
4266
|
-
deps
|
|
4308
|
+
deps,
|
|
4309
|
+
failedDownloads
|
|
4267
4310
|
);
|
|
4268
4311
|
const finalLocalSkills = await deps.scanLocalSkills(syncPaths);
|
|
4269
4312
|
const lastSyncedAt = pullResponse.last_synced_at || (/* @__PURE__ */ new Date()).toISOString();
|
|
4270
4313
|
const relinkSkillNames = new Set(options.relinkSkillNames || []);
|
|
4314
|
+
const failures = [...failedDownloads];
|
|
4315
|
+
const verifiedLinks = {};
|
|
4316
|
+
for (const skill of pullResponse.skills) {
|
|
4317
|
+
const previous = previousState.skills[skill.name];
|
|
4318
|
+
if (skill.updated_at && previous?.cloudId === skill.id && previous.cloudUpdatedAt === skill.updated_at) {
|
|
4319
|
+
verifiedLinks[skill.name] = { ...previous.verifiedAgentLinks };
|
|
4320
|
+
}
|
|
4321
|
+
}
|
|
4271
4322
|
if (relinkSkillNames.size > 0) {
|
|
4272
|
-
await deps.syncSymlinks(
|
|
4323
|
+
const relinked = await deps.syncSymlinks(
|
|
4273
4324
|
pullResponse.skills.filter((skill) => relinkSkillNames.has(skill.name)),
|
|
4274
4325
|
syncPaths.skillsDir,
|
|
4275
4326
|
{ removeUndesired: false }
|
|
4276
4327
|
);
|
|
4328
|
+
failures.push(...(relinked.failures ?? []).filter(
|
|
4329
|
+
(failure) => !failedDownloads.some((download) => download.name === failure.name)
|
|
4330
|
+
));
|
|
4331
|
+
for (const name of relinkSkillNames) {
|
|
4332
|
+
verifiedLinks[name] = relinked.verifiedAgentLinks?.[name] ?? {};
|
|
4333
|
+
}
|
|
4277
4334
|
}
|
|
4335
|
+
for (const failure of failedDownloads) delete verifiedLinks[failure.name];
|
|
4278
4336
|
await deps.writeSyncState(
|
|
4279
|
-
buildSyncState(pullResponse, finalLocalSkills, lastSyncedAt),
|
|
4337
|
+
buildSyncState(pullResponse, finalLocalSkills, lastSyncedAt, verifiedLinks),
|
|
4280
4338
|
syncPaths
|
|
4281
4339
|
);
|
|
4282
4340
|
return {
|
|
@@ -4284,10 +4342,11 @@ async function materializeCloudSkillsForLocalShell(serverUrl, jwt, dependencies
|
|
|
4284
4342
|
downloaded,
|
|
4285
4343
|
deleted: 0,
|
|
4286
4344
|
removed: 0,
|
|
4287
|
-
lastSyncedAt
|
|
4345
|
+
lastSyncedAt,
|
|
4346
|
+
...failures.length ? { failedLinks: failures } : {}
|
|
4288
4347
|
};
|
|
4289
4348
|
}
|
|
4290
|
-
async function deactivateDeletedAgentSkills(serverUrl, jwt, pullResponse, previousState, scopedState, skillsDir, deps) {
|
|
4349
|
+
async function deactivateDeletedAgentSkills(serverUrl, jwt, pullResponse, previousState, scopedState, skillsDir, deps, failures) {
|
|
4291
4350
|
if (isEmptySyncState(scopedState)) {
|
|
4292
4351
|
return 0;
|
|
4293
4352
|
}
|
|
@@ -4299,22 +4358,6 @@ async function deactivateDeletedAgentSkills(serverUrl, jwt, pullResponse, previo
|
|
|
4299
4358
|
if (deletions.length === 0) {
|
|
4300
4359
|
return 0;
|
|
4301
4360
|
}
|
|
4302
|
-
const latestSkillsById = new Map(pullResponse.skills.map((skill) => [skill.id, skill]));
|
|
4303
|
-
let fresh = null;
|
|
4304
|
-
try {
|
|
4305
|
-
fresh = await deps.pullSkills(serverUrl, jwt);
|
|
4306
|
-
} catch (error) {
|
|
4307
|
-
console.warn(
|
|
4308
|
-
"[skill-sync] Could not re-pull latest agent targets before deactivation; using the top-of-sync snapshot.",
|
|
4309
|
-
error
|
|
4310
|
-
);
|
|
4311
|
-
}
|
|
4312
|
-
if (fresh) {
|
|
4313
|
-
assertSkillsPullAuthorized(fresh);
|
|
4314
|
-
for (const skill of fresh.skills) {
|
|
4315
|
-
latestSkillsById.set(skill.id, skill);
|
|
4316
|
-
}
|
|
4317
|
-
}
|
|
4318
4361
|
const agentsBySkill = /* @__PURE__ */ new Map();
|
|
4319
4362
|
for (const deletion of deletions) {
|
|
4320
4363
|
const entry = agentsBySkill.get(deletion.skillId) ?? {
|
|
@@ -4324,31 +4367,35 @@ async function deactivateDeletedAgentSkills(serverUrl, jwt, pullResponse, previo
|
|
|
4324
4367
|
entry.agents.add(deletion.agent);
|
|
4325
4368
|
agentsBySkill.set(deletion.skillId, entry);
|
|
4326
4369
|
}
|
|
4327
|
-
const
|
|
4370
|
+
const fresh = withoutBaseSkills(await deps.pullSkills(serverUrl, jwt));
|
|
4371
|
+
assertSkillsPullAuthorized(fresh);
|
|
4372
|
+
Object.assign(pullResponse, fresh);
|
|
4373
|
+
let needsRefresh = false;
|
|
4328
4374
|
let deactivated = 0;
|
|
4329
4375
|
for (const [skillId, { skillName, agents }] of agentsBySkill) {
|
|
4330
|
-
const
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
const nextTargets = { ...normalizeAgentTargets(latest.agent_targets) };
|
|
4335
|
-
for (const agent of agents) {
|
|
4336
|
-
nextTargets[agent] = false;
|
|
4337
|
-
}
|
|
4376
|
+
const skill = pullResponse.skills.find((item) => item.id === skillId);
|
|
4377
|
+
const previous = previousState.skills[skillName];
|
|
4378
|
+
if (!skill?.updated_at || previous?.cloudUpdatedAt !== skill.updated_at) continue;
|
|
4379
|
+
const patch = Object.fromEntries([...agents].map((agent) => [agent, false]));
|
|
4338
4380
|
try {
|
|
4339
|
-
await deps.updateAgentTargets(serverUrl, jwt, skillId,
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
inMemory.agent_targets = nextTargets;
|
|
4381
|
+
const saved = await deps.updateAgentTargets(serverUrl, jwt, skillId, patch, skill.updated_at);
|
|
4382
|
+
if (saved.success !== true || !saved.updated_at?.trim() || saved.updated_at === skill.updated_at || !["notis", "claude_code", "cursor", "codex"].every((agent) => typeof saved.agent_targets?.[agent] === "boolean") || ![...agents].every((agent) => saved.agent_targets[agent] === false)) {
|
|
4383
|
+
throw new Error("Assignment update did not return a verified saved revision");
|
|
4343
4384
|
}
|
|
4385
|
+
skill.agent_targets = saved.agent_targets;
|
|
4386
|
+
skill.updated_at = saved.updated_at;
|
|
4344
4387
|
deactivated += agents.size;
|
|
4345
4388
|
} catch (error) {
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
);
|
|
4389
|
+
needsRefresh = true;
|
|
4390
|
+
failures.push({ name: skillName, error: "Could not save the local agent removal; refreshed saved assignments" });
|
|
4391
|
+
console.warn(`[skill-sync] Assignment changed or could not be saved for "${skillName}"; refreshing before reconciliation.`, error);
|
|
4350
4392
|
}
|
|
4351
4393
|
}
|
|
4394
|
+
if (needsRefresh) {
|
|
4395
|
+
const refreshed = withoutBaseSkills(await deps.pullSkills(serverUrl, jwt));
|
|
4396
|
+
assertSkillsPullAuthorized(refreshed);
|
|
4397
|
+
Object.assign(pullResponse, refreshed);
|
|
4398
|
+
}
|
|
4352
4399
|
return deactivated;
|
|
4353
4400
|
}
|
|
4354
4401
|
async function runSkillSync(serverUrl, jwt, dependencies = {}, options = {}) {
|
|
@@ -4391,6 +4438,18 @@ async function runSkillSync(serverUrl, jwt, dependencies = {}, options = {}) {
|
|
|
4391
4438
|
pullResponse.skills.filter((skill) => skill.source === "curated").map((skill) => skill.name)
|
|
4392
4439
|
);
|
|
4393
4440
|
const protectedSkillNames = /* @__PURE__ */ new Set([...cloudCuratedSkillNames, ...BASE_SKILL_NAMES2]);
|
|
4441
|
+
const scopedState = withoutBaseSkillState(await deps.readSyncState(syncPaths));
|
|
4442
|
+
const assignmentFailures = [];
|
|
4443
|
+
const deactivated = syncSettings.agent_targets_conditional_updates === true ? await deactivateDeletedAgentSkills(
|
|
4444
|
+
serverUrl,
|
|
4445
|
+
jwt,
|
|
4446
|
+
pullResponse,
|
|
4447
|
+
scopedState,
|
|
4448
|
+
scopedState,
|
|
4449
|
+
syncPaths.skillsDir,
|
|
4450
|
+
deps,
|
|
4451
|
+
assignmentFailures
|
|
4452
|
+
) : 0;
|
|
4394
4453
|
const authUserId = decodeJwtSubject(jwt);
|
|
4395
4454
|
let previousAuthState = null;
|
|
4396
4455
|
if (authUserId && authUserId !== syncUserId) {
|
|
@@ -4405,22 +4464,12 @@ async function runSkillSync(serverUrl, jwt, dependencies = {}, options = {}) {
|
|
|
4405
4464
|
protectedSkillNames
|
|
4406
4465
|
});
|
|
4407
4466
|
const localSkills = (await deps.scanLocalSkills(syncPaths)).filter((skill) => !BASE_SKILL_NAMES2.has(skill.name));
|
|
4408
|
-
const scopedState = withoutBaseSkillState(await deps.readSyncState(syncPaths));
|
|
4409
4467
|
const previousState = withoutBaseSkillState(applyLegacyFirstRunState(
|
|
4410
4468
|
localSkills,
|
|
4411
4469
|
scopedState,
|
|
4412
4470
|
isEmptySyncState(scopedState) ? !previousAuthState || isEmptySyncState(previousAuthState) ? await deps.readLegacySyncState(syncPaths) : previousAuthState : null
|
|
4413
4471
|
));
|
|
4414
|
-
const
|
|
4415
|
-
serverUrl,
|
|
4416
|
-
jwt,
|
|
4417
|
-
pullResponse,
|
|
4418
|
-
previousState,
|
|
4419
|
-
scopedState,
|
|
4420
|
-
syncPaths.skillsDir,
|
|
4421
|
-
deps
|
|
4422
|
-
);
|
|
4423
|
-
await deps.syncSymlinks(
|
|
4472
|
+
const gatheredSymlinkResult = await deps.syncSymlinks(
|
|
4424
4473
|
buildLocalSymlinkCandidates(pullResponse, localSkills, previousState),
|
|
4425
4474
|
syncPaths.skillsDir
|
|
4426
4475
|
);
|
|
@@ -4451,21 +4500,25 @@ async function runSkillSync(serverUrl, jwt, dependencies = {}, options = {}) {
|
|
|
4451
4500
|
deleted += 1;
|
|
4452
4501
|
}
|
|
4453
4502
|
}
|
|
4503
|
+
const failedDownloads = [];
|
|
4454
4504
|
const downloaded = await writePulledSkillsToScopedMirror(
|
|
4455
4505
|
pullResponse,
|
|
4456
4506
|
localSkills,
|
|
4457
4507
|
previousState,
|
|
4458
4508
|
syncPaths,
|
|
4459
|
-
deps
|
|
4509
|
+
deps,
|
|
4510
|
+
failedDownloads
|
|
4460
4511
|
);
|
|
4461
4512
|
const finalLocalSkills = (await deps.scanLocalSkills(syncPaths)).filter((skill) => !BASE_SKILL_NAMES2.has(skill.name));
|
|
4462
4513
|
const symlinkResult = await deps.syncSymlinks(
|
|
4463
4514
|
buildLocalSymlinkCandidates(pullResponse, finalLocalSkills, previousState),
|
|
4464
4515
|
syncPaths.skillsDir
|
|
4465
4516
|
);
|
|
4517
|
+
const verifiedLinks = { ...symlinkResult.verifiedAgentLinks ?? {} };
|
|
4518
|
+
for (const failure of failedDownloads) delete verifiedLinks[failure.name];
|
|
4466
4519
|
const lastSyncedAt = pullResponse.last_synced_at || (/* @__PURE__ */ new Date()).toISOString();
|
|
4467
4520
|
await deps.writeSyncState(
|
|
4468
|
-
buildSyncState(pullResponse, finalLocalSkills, lastSyncedAt),
|
|
4521
|
+
buildSyncState(pullResponse, finalLocalSkills, lastSyncedAt, verifiedLinks),
|
|
4469
4522
|
syncPaths
|
|
4470
4523
|
);
|
|
4471
4524
|
return {
|
|
@@ -4475,14 +4528,17 @@ async function runSkillSync(serverUrl, jwt, dependencies = {}, options = {}) {
|
|
|
4475
4528
|
downloaded,
|
|
4476
4529
|
deleted,
|
|
4477
4530
|
deactivated,
|
|
4478
|
-
linked: symlinkResult.linked,
|
|
4479
|
-
removed: foreignLinksRemoved + symlinkResult.removed,
|
|
4531
|
+
linked: gatheredSymlinkResult.linked + symlinkResult.linked,
|
|
4532
|
+
removed: foreignLinksRemoved + gatheredSymlinkResult.removed + symlinkResult.removed,
|
|
4480
4533
|
skipped: symlinkResult.skipped,
|
|
4534
|
+
failedLinks: [...assignmentFailures, ...failedDownloads, ...(symlinkResult.failures ?? []).filter(
|
|
4535
|
+
(failure) => !failedDownloads.some((download) => download.name === failure.name)
|
|
4536
|
+
)],
|
|
4481
4537
|
lastSyncedAt,
|
|
4482
4538
|
failedPushes
|
|
4483
4539
|
};
|
|
4484
4540
|
}
|
|
4485
|
-
var DEFAULT_AGENT_TARGETS, HOME_DIR, execFileAsync, AGENTS_DIR, LEGACY_AGENTS_SKILLS_DIR, NOTIS_SKILL_SYNC_ROOT, LEGACY_NOTIS_SYNC_STATE_PATH, AGENTS_SKILLS_DIR, SKILL_LOCK_PATH, DEFAULT_SYNC_STATE, EXCLUDED_TOP_LEVEL_ROOT_NAMES, DEFAULT_SYNC_PATHS, HOME_DIR2, EXTERNAL_AGENT_SKILL_DIRS, EXTERNAL_AGENTS, BASE_SKILL_NAMES2, DEFAULT_RUN_SKILL_SYNC_DEPS;
|
|
4541
|
+
var DEFAULT_AGENT_TARGETS, HOME_DIR, execFileAsync, AGENTS_DIR, LEGACY_AGENTS_SKILLS_DIR, NOTIS_SKILL_SYNC_ROOT, LEGACY_NOTIS_SYNC_STATE_PATH, AGENTS_SKILLS_DIR, SKILL_LOCK_PATH, DEFAULT_SYNC_STATE, EXCLUDED_TOP_LEVEL_ROOT_NAMES, DEFAULT_SYNC_PATHS, HOME_DIR2, EXTERNAL_AGENT_SKILL_DIRS, EXTERNAL_AGENTS, AGENT_FAILURE_LABELS, BASE_SKILL_NAMES2, DEFAULT_RUN_SKILL_SYNC_DEPS;
|
|
4486
4542
|
var init_skill_sync = __esm({
|
|
4487
4543
|
"dist/skill-sync/index.js"() {
|
|
4488
4544
|
DEFAULT_AGENT_TARGETS = {
|
|
@@ -4541,6 +4597,12 @@ var init_skill_sync = __esm({
|
|
|
4541
4597
|
codex: path2.join(HOME_DIR2, ".codex", "skills")
|
|
4542
4598
|
};
|
|
4543
4599
|
EXTERNAL_AGENTS = Object.keys(EXTERNAL_AGENT_SKILL_DIRS);
|
|
4600
|
+
AGENT_FAILURE_LABELS = {
|
|
4601
|
+
claude_code: "Claude Code",
|
|
4602
|
+
cursor: "Cursor",
|
|
4603
|
+
codex: "Codex",
|
|
4604
|
+
legacy: "legacy ~/.agents/skills"
|
|
4605
|
+
};
|
|
4544
4606
|
BASE_SKILL_NAMES2 = /* @__PURE__ */ new Set(["notis-apps", "notis-query", "notis-cli"]);
|
|
4545
4607
|
DEFAULT_RUN_SKILL_SYNC_DEPS = {
|
|
4546
4608
|
fetchSyncSettings,
|
|
@@ -4566,7 +4628,7 @@ var init_skill_sync = __esm({
|
|
|
4566
4628
|
// src/cli.js
|
|
4567
4629
|
import { readFileSync as readFileSync21 } from "node:fs";
|
|
4568
4630
|
import { dirname as dirname18, join as join19 } from "node:path";
|
|
4569
|
-
import { fileURLToPath as
|
|
4631
|
+
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
4570
4632
|
|
|
4571
4633
|
// node_modules/commander/esm.mjs
|
|
4572
4634
|
var import_index = __toESM(require_commander(), 1);
|
|
@@ -7721,7 +7783,7 @@ async function directDeploy(projectDir, appId) {
|
|
|
7721
7783
|
|
|
7722
7784
|
// src/runtime/app-dev-server.js
|
|
7723
7785
|
import { createServer } from "node:http";
|
|
7724
|
-
import { execFileSync as execFileSync2, spawn as
|
|
7786
|
+
import { execFileSync as execFileSync2, spawn as spawn3 } from "node:child_process";
|
|
7725
7787
|
import {
|
|
7726
7788
|
appendFileSync,
|
|
7727
7789
|
existsSync as existsSync7,
|
|
@@ -7735,7 +7797,7 @@ import {
|
|
|
7735
7797
|
import { freemem, loadavg, totalmem } from "node:os";
|
|
7736
7798
|
import { dirname as dirname6, join as join7, resolve as resolve5 } from "node:path";
|
|
7737
7799
|
import { setTimeout as delay } from "node:timers/promises";
|
|
7738
|
-
import { fileURLToPath as
|
|
7800
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
7739
7801
|
|
|
7740
7802
|
// src/runtime/app-dev-sessions.js
|
|
7741
7803
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
@@ -8900,6 +8962,40 @@ function captureDesktopHostOwnership({
|
|
|
8900
8962
|
};
|
|
8901
8963
|
}
|
|
8902
8964
|
|
|
8965
|
+
// src/runtime/app-dev-build.js
|
|
8966
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
8967
|
+
import { EventEmitter } from "node:events";
|
|
8968
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
8969
|
+
async function startAppDevBuild(cwd, command = "npm", args = ["run", "build", "--", "--watch"]) {
|
|
8970
|
+
const supervisor = spawn2(process.execPath, [fileURLToPath3(new URL("./app-dev-build-supervisor.js", import.meta.url))], {
|
|
8971
|
+
cwd,
|
|
8972
|
+
stdio: ["ignore", "inherit", "inherit", "ipc"],
|
|
8973
|
+
env: { ...process.env, ELECTRON_RUN_AS_NODE: "1", NOTIS_DEV: "1" }
|
|
8974
|
+
});
|
|
8975
|
+
const build = new EventEmitter();
|
|
8976
|
+
build.pid = null;
|
|
8977
|
+
build.exitCode = null;
|
|
8978
|
+
build.signalCode = null;
|
|
8979
|
+
build.kill = (signal = "SIGTERM") => supervisor.kill(signal);
|
|
8980
|
+
await new Promise((resolve10, reject) => {
|
|
8981
|
+
supervisor.once("error", reject);
|
|
8982
|
+
supervisor.once("exit", (code, signal) => {
|
|
8983
|
+
build.exitCode = code;
|
|
8984
|
+
build.signalCode = signal;
|
|
8985
|
+
reject(new Error(`Build supervisor exited before startup (${code ?? signal})`));
|
|
8986
|
+
build.emit("exit", code, signal);
|
|
8987
|
+
});
|
|
8988
|
+
supervisor.once("message", ({ pid }) => {
|
|
8989
|
+
build.pid = pid;
|
|
8990
|
+
resolve10();
|
|
8991
|
+
});
|
|
8992
|
+
supervisor.send({ command, args }, (error) => {
|
|
8993
|
+
if (error) reject(error);
|
|
8994
|
+
});
|
|
8995
|
+
});
|
|
8996
|
+
return build;
|
|
8997
|
+
}
|
|
8998
|
+
|
|
8903
8999
|
// src/runtime/app-dev-server.js
|
|
8904
9000
|
var CONTENT_TYPES = {
|
|
8905
9001
|
".js": "application/javascript; charset=utf-8",
|
|
@@ -8907,7 +9003,7 @@ var CONTENT_TYPES = {
|
|
|
8907
9003
|
".map": "application/json; charset=utf-8"
|
|
8908
9004
|
};
|
|
8909
9005
|
var MAX_JSON_BODY_BYTES = 64 * 1024;
|
|
8910
|
-
var RUNTIME_DIR = dirname6(
|
|
9006
|
+
var RUNTIME_DIR = dirname6(fileURLToPath4(import.meta.url));
|
|
8911
9007
|
var CLI_ROOT2 = resolve5(RUNTIME_DIR, "../..");
|
|
8912
9008
|
var REPO_ROOT = resolve5(RUNTIME_DIR, "../../../..");
|
|
8913
9009
|
var HARNESS_TEMPLATE_PATH = join7(CLI_ROOT2, "template", ".harness", "index.html.tmpl");
|
|
@@ -8948,7 +9044,7 @@ function readProcessGroupRssBytes(groupPids) {
|
|
|
8948
9044
|
async function terminateBuildProcessTree(child, {
|
|
8949
9045
|
platform = process.platform,
|
|
8950
9046
|
signalProcess = process.kill,
|
|
8951
|
-
spawnProcess =
|
|
9047
|
+
spawnProcess = spawn3,
|
|
8952
9048
|
graceMs = BUILD_PROCESS_STOP_GRACE_MS
|
|
8953
9049
|
} = {}) {
|
|
8954
9050
|
const pid = child?.pid;
|
|
@@ -9755,12 +9851,7 @@ data: ${JSON.stringify({ slug, at: Date.now() })}
|
|
|
9755
9851
|
await prepareArtifactBuild(state.projectDir);
|
|
9756
9852
|
watchManifestInputs(state);
|
|
9757
9853
|
pollForBundleAndWatch(state);
|
|
9758
|
-
const buildProcess =
|
|
9759
|
-
cwd: state.projectDir,
|
|
9760
|
-
detached: process.platform !== "win32",
|
|
9761
|
-
stdio: "inherit",
|
|
9762
|
-
env: { ...process.env, NOTIS_DEV: "1" }
|
|
9763
|
-
});
|
|
9854
|
+
const buildProcess = await startAppDevBuild(state.projectDir);
|
|
9764
9855
|
state.buildProcess = buildProcess;
|
|
9765
9856
|
for (let attempt = 0; attempt < 5 && !state.watcherOwnership; attempt += 1) {
|
|
9766
9857
|
state.watcherOwnership = captureDesktopWatcherOwnership({
|
|
@@ -10122,7 +10213,7 @@ function discoverRegisteredAppProjects(options = {}) {
|
|
|
10122
10213
|
}
|
|
10123
10214
|
|
|
10124
10215
|
// src/runtime/agent-browser.js
|
|
10125
|
-
import { spawn as
|
|
10216
|
+
import { spawn as spawn4, spawnSync } from "node:child_process";
|
|
10126
10217
|
import { mkdirSync as mkdirSync7, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
10127
10218
|
import { dirname as dirname8 } from "node:path";
|
|
10128
10219
|
var PREPARE_CAPTURE_SCRIPT = "(() => { const s = document.getElementById('harness-status'); if (s) s.style.display = 'none'; const r = document.getElementById('root'); if (r) { r.style.paddingTop = '0'; r.style.minHeight = '0'; } document.body.style.minHeight = '0'; document.documentElement.style.minHeight = '0'; return true; })()";
|
|
@@ -10215,7 +10306,7 @@ function commandError(phase, result) {
|
|
|
10215
10306
|
}
|
|
10216
10307
|
function runAgentBrowser(args, { timeoutMs = 3e4 } = {}) {
|
|
10217
10308
|
return new Promise((resolvePromise) => {
|
|
10218
|
-
const child =
|
|
10309
|
+
const child = spawn4("agent-browser", args, {
|
|
10219
10310
|
stdio: ["ignore", "pipe", "pipe"],
|
|
10220
10311
|
env: process.env
|
|
10221
10312
|
});
|
|
@@ -10748,9 +10839,9 @@ function getCliMode() {
|
|
|
10748
10839
|
}
|
|
10749
10840
|
|
|
10750
10841
|
// src/runtime/store-screenshot.js
|
|
10751
|
-
import { fileURLToPath as
|
|
10842
|
+
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
10752
10843
|
var STORE_SCREENSHOT_ASPECT = 16 / 10;
|
|
10753
|
-
var SHARED_BACKDROP_PATH =
|
|
10844
|
+
var SHARED_BACKDROP_PATH = fileURLToPath5(
|
|
10754
10845
|
new URL("./assets/store-screenshot-dark.png", import.meta.url)
|
|
10755
10846
|
);
|
|
10756
10847
|
var ACCENT_PALETTES = {
|
|
@@ -10924,8 +11015,8 @@ import {
|
|
|
10924
11015
|
import { createServer as createServer3 } from "node:http";
|
|
10925
11016
|
import { homedir as homedir6 } from "node:os";
|
|
10926
11017
|
import { basename as basename2, dirname as dirname10, join as join11 } from "node:path";
|
|
10927
|
-
import { fileURLToPath as
|
|
10928
|
-
import { execFileSync as execFileSync3, spawn as
|
|
11018
|
+
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
11019
|
+
import { execFileSync as execFileSync3, spawn as spawn5 } from "node:child_process";
|
|
10929
11020
|
import { createInterface } from "node:readline/promises";
|
|
10930
11021
|
var DEFAULT_CLI_OAUTH_SCOPES = [
|
|
10931
11022
|
"notis:read",
|
|
@@ -11462,7 +11553,7 @@ function browserOpenCommand(url, platform = process.platform) {
|
|
|
11462
11553
|
function openBrowser(url) {
|
|
11463
11554
|
const { command, args } = browserOpenCommand(url);
|
|
11464
11555
|
try {
|
|
11465
|
-
const child =
|
|
11556
|
+
const child = spawn5(command, args, { detached: true, stdio: "ignore" });
|
|
11466
11557
|
child.on("error", () => {
|
|
11467
11558
|
});
|
|
11468
11559
|
child.unref();
|
|
@@ -11638,7 +11729,7 @@ async function publishForegroundAuthorization(runtime, authorization) {
|
|
|
11638
11729
|
releaseListenerGlobalLock(globalLock);
|
|
11639
11730
|
}
|
|
11640
11731
|
}
|
|
11641
|
-
var LISTENER_SCRIPT =
|
|
11732
|
+
var LISTENER_SCRIPT = fileURLToPath6(new URL("./login-listener.js", import.meta.url));
|
|
11642
11733
|
var LISTENER_SCRIPT_NAME = "login-listener.js";
|
|
11643
11734
|
var LISTENER_HANDSHAKE_TIMEOUT_MS = 1e4;
|
|
11644
11735
|
var LISTENER_START_LOCK_STALE_MS = LISTENER_HANDSHAKE_TIMEOUT_MS * 2;
|
|
@@ -11938,7 +12029,7 @@ async function startDetachedLoopbackListener(runtime, {
|
|
|
11938
12029
|
}
|
|
11939
12030
|
let child;
|
|
11940
12031
|
try {
|
|
11941
|
-
child =
|
|
12032
|
+
child = spawn5(process.execPath, [LISTENER_SCRIPT, payloadFile, identityToken], {
|
|
11942
12033
|
detached: true,
|
|
11943
12034
|
windowsHide: true,
|
|
11944
12035
|
// An IPC channel only so the child can report the port it bound. Every
|
|
@@ -13739,7 +13830,7 @@ function runtimeCallLabel(call) {
|
|
|
13739
13830
|
}
|
|
13740
13831
|
return call?.op || "runtime call";
|
|
13741
13832
|
}
|
|
13742
|
-
function assertHarnessResult(result, route, databaseSlugs, mode = "stub") {
|
|
13833
|
+
function assertHarnessResult(result, route, databaseSlugs, mode = "stub", capabilities = {}) {
|
|
13743
13834
|
const assertions = [];
|
|
13744
13835
|
if (result.tool_error) {
|
|
13745
13836
|
assertions.push({
|
|
@@ -13778,7 +13869,7 @@ function assertHarnessResult(result, route, databaseSlugs, mode = "stub") {
|
|
|
13778
13869
|
);
|
|
13779
13870
|
for (const call of databaseQueries) {
|
|
13780
13871
|
const databaseSlug = call?.args?.arguments?.database_slug;
|
|
13781
|
-
if (databaseSlug && !declaredDatabaseSet.has(databaseSlug)) {
|
|
13872
|
+
if (databaseSlug && !declaredDatabaseSet.has(databaseSlug) && capabilities.workspaceDatabases !== "read") {
|
|
13782
13873
|
assertions.push({
|
|
13783
13874
|
ok: false,
|
|
13784
13875
|
code: "undeclared_database_query",
|
|
@@ -14872,7 +14963,8 @@ ${listing.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
|
14872
14963
|
result,
|
|
14873
14964
|
route,
|
|
14874
14965
|
declaredDatabaseSlugs(appConfig, manifest, route),
|
|
14875
|
-
mode
|
|
14966
|
+
mode,
|
|
14967
|
+
manifest.capabilities || appConfig.capabilities || {}
|
|
14876
14968
|
);
|
|
14877
14969
|
return {
|
|
14878
14970
|
...result,
|
|
@@ -14897,7 +14989,8 @@ ${listing.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
|
14897
14989
|
result,
|
|
14898
14990
|
route,
|
|
14899
14991
|
declaredDatabaseSlugs(appConfig, manifest, route),
|
|
14900
|
-
mode
|
|
14992
|
+
mode,
|
|
14993
|
+
manifest.capabilities || appConfig.capabilities || {}
|
|
14901
14994
|
);
|
|
14902
14995
|
results.push({
|
|
14903
14996
|
route: route.slug,
|
|
@@ -16036,6 +16129,11 @@ function classifySqlMutation(query) {
|
|
|
16036
16129
|
}
|
|
16037
16130
|
function classifyToolMutation(toolName, args = {}) {
|
|
16038
16131
|
const normalized = localNotisToolSlug(toolName).toUpperCase();
|
|
16132
|
+
if (normalized === "LOCAL_NOTIS_SANDBOX_PREVIEW") {
|
|
16133
|
+
if (args.action === "status") return false;
|
|
16134
|
+
if (["register", "open", "heartbeat", "stop"].includes(args.action)) return true;
|
|
16135
|
+
return null;
|
|
16136
|
+
}
|
|
16039
16137
|
if (normalized.includes("EXECUTE_SQL") && typeof args.query === "string") {
|
|
16040
16138
|
const query = args.query.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/--[^\n]*/g, " ").trim();
|
|
16041
16139
|
const sqlClassification = classifySqlMutation(query);
|
|
@@ -16504,7 +16602,7 @@ var toolsCommandSpecs = [
|
|
|
16504
16602
|
|
|
16505
16603
|
// src/command-specs/meta.js
|
|
16506
16604
|
import { dirname as dirname12 } from "node:path";
|
|
16507
|
-
import { fileURLToPath as
|
|
16605
|
+
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
16508
16606
|
|
|
16509
16607
|
// src/runtime/help.js
|
|
16510
16608
|
function canonicalCommandName(spec) {
|
|
@@ -16567,7 +16665,7 @@ function doctorToolRoundtripRuntime(runtime) {
|
|
|
16567
16665
|
timeoutMs: Math.max(runtime.timeoutMs || 0, DOCTOR_TOOL_ROUNDTRIP_TIMEOUT_MS)
|
|
16568
16666
|
};
|
|
16569
16667
|
}
|
|
16570
|
-
function doctorChannelSummary(runtime, moduleDirectory = dirname12(
|
|
16668
|
+
function doctorChannelSummary(runtime, moduleDirectory = dirname12(fileURLToPath7(import.meta.url))) {
|
|
16571
16669
|
const decision = resolveChannelSwitch({
|
|
16572
16670
|
runningVersion: runtime.cliVersion,
|
|
16573
16671
|
profile: {
|
|
@@ -16782,7 +16880,7 @@ var metaCommandSpecs = [
|
|
|
16782
16880
|
// src/command-specs/onboarding.js
|
|
16783
16881
|
import { readFileSync as readFileSync17 } from "node:fs";
|
|
16784
16882
|
import { dirname as dirname15, join as join15 } from "node:path";
|
|
16785
|
-
import { fileURLToPath as
|
|
16883
|
+
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
16786
16884
|
|
|
16787
16885
|
// src/command-specs/agents.js
|
|
16788
16886
|
import { createHash as createHash6 } from "node:crypto";
|
|
@@ -16801,8 +16899,8 @@ import {
|
|
|
16801
16899
|
import { createHash as createHash4 } from "node:crypto";
|
|
16802
16900
|
import { homedir as homedir7 } from "node:os";
|
|
16803
16901
|
import { dirname as dirname13, join as join13 } from "node:path";
|
|
16804
|
-
import { fileURLToPath as
|
|
16805
|
-
var HERE = dirname13(
|
|
16902
|
+
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
16903
|
+
var HERE = dirname13(fileURLToPath8(import.meta.url));
|
|
16806
16904
|
var INSTRUCTIONS_PATH = join13(HERE, "..", "..", "skills", "notis-cli", "AGENT_INSTRUCTIONS.md");
|
|
16807
16905
|
var HOOK_BUNDLE_PATH = join13(HERE, "..", "..", "dist", "agent-hooks", "notis-agent-hook.mjs");
|
|
16808
16906
|
var START_MARKER = "<!-- notis-cli:instructions:start -->";
|
|
@@ -17641,7 +17739,7 @@ var authCommandSpecs = [
|
|
|
17641
17739
|
];
|
|
17642
17740
|
|
|
17643
17741
|
// src/command-specs/onboarding.js
|
|
17644
|
-
var HERE2 = dirname15(
|
|
17742
|
+
var HERE2 = dirname15(fileURLToPath9(import.meta.url));
|
|
17645
17743
|
var BUNDLED_BRIEF_PATH = join15(HERE2, "..", "..", "skills", "notis-onboarding", "BRIEF.md");
|
|
17646
17744
|
async function fetchOnboardingState(runtime) {
|
|
17647
17745
|
try {
|
|
@@ -19536,13 +19634,13 @@ import {
|
|
|
19536
19634
|
} from "node:fs";
|
|
19537
19635
|
import { homedir as homedir9 } from "node:os";
|
|
19538
19636
|
import { dirname as dirname16, join as join17, relative as relative5, resolve as resolve9 } from "node:path";
|
|
19539
|
-
import { fileURLToPath as
|
|
19637
|
+
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
19540
19638
|
var BASE_SKILL_NAMES = Object.freeze([
|
|
19541
19639
|
"notis-apps",
|
|
19542
19640
|
"notis-query",
|
|
19543
19641
|
"notis-cli"
|
|
19544
19642
|
]);
|
|
19545
|
-
var HERE3 = dirname16(
|
|
19643
|
+
var HERE3 = dirname16(fileURLToPath10(import.meta.url));
|
|
19546
19644
|
function resolveBundledBaseSkillsRoot({ resourcesPath = process.resourcesPath } = {}) {
|
|
19547
19645
|
const sourceCheckout = resolve9(HERE3, "../../../../server/skills");
|
|
19548
19646
|
const packaged = resolve9(HERE3, "../../dist/base-skills");
|
|
@@ -19850,11 +19948,12 @@ async function syncSkillsHandler(ctx) {
|
|
|
19850
19948
|
honorSyncEnabled: Boolean(ctx.options.electronRepeat),
|
|
19851
19949
|
runAccountSync: runSkillSync2
|
|
19852
19950
|
});
|
|
19951
|
+
const failures = [...result.failedPushes || [], ...result.failedLinks || []];
|
|
19853
19952
|
return ctx.output.emitSuccess({
|
|
19854
19953
|
command: "skills sync",
|
|
19855
19954
|
data: result,
|
|
19856
|
-
humanSummary: result.syncEnabled ? `Synced account skills and kept ${result.baseSkills.length} base skills current.` : `Automatic Desktop sync is off; kept ${result.baseSkills.length} base skills current.`,
|
|
19857
|
-
renderHuman: () => result.syncEnabled ? `Skills synced. Base skills current: ${result.baseSkills.join(", ")}.` : `Automatic Desktop sync is off. Base skills remain current: ${result.baseSkills.join(", ")}.`
|
|
19955
|
+
humanSummary: failures.length ? `Skill sync completed with ${failures.length} reported failures; inspect failedPushes and failedLinks.` : result.syncEnabled ? `Synced account skills and kept ${result.baseSkills.length} base skills current.` : `Automatic Desktop sync is off; kept ${result.baseSkills.length} base skills current.`,
|
|
19956
|
+
renderHuman: () => failures.length ? `Skill sync needs attention: ${failures.map((failure) => `${failure.name}: ${failure.error}`).join("; ")}` : result.syncEnabled ? `Skills synced. Base skills current: ${result.baseSkills.join(", ")}.` : `Automatic Desktop sync is off. Base skills remain current: ${result.baseSkills.join(", ")}.`
|
|
19858
19957
|
});
|
|
19859
19958
|
}
|
|
19860
19959
|
var skillsCommandSpecs = [
|
|
@@ -19990,7 +20089,7 @@ async function reportCliCommand({
|
|
|
19990
20089
|
// src/cli.js
|
|
19991
20090
|
function readCliVersion() {
|
|
19992
20091
|
try {
|
|
19993
|
-
const manifestPath = join19(dirname18(
|
|
20092
|
+
const manifestPath = join19(dirname18(fileURLToPath11(import.meta.url)), "..", "package.json");
|
|
19994
20093
|
const version = JSON.parse(readFileSync21(manifestPath, "utf-8")).version;
|
|
19995
20094
|
if (typeof version === "string" && version.trim()) {
|
|
19996
20095
|
return version.trim();
|