grok-bot-cli 0.6.0 → 0.8.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/CHANGELOG.md +19 -0
- package/dist/.claude-plugin/marketplace.json +1 -1
- package/dist/.claude-plugin/plugin.json +1 -1
- package/dist/.codex-plugin/plugin.json +1 -1
- package/dist/.cursor-plugin/plugin.json +1 -1
- package/dist/INSTALL.md +1 -1
- package/dist/agent-bundle.compile-evidence.json +1 -1
- package/dist/agent-bundle.manifest.json +1 -1
- package/dist/agent-bundle.package-compile-evidence.json +1 -1
- package/dist/bin/gbot-flight.mjs +380 -116
- package/dist/bin/gbot-install.js +9085 -9082
- package/dist/bin/gbot.mjs +476 -121
- package/dist/install.mjs +19 -9
- package/dist/mcp/mcp-grok-bot-b8c2461e-flight.mjs +425 -29
- package/dist/mcp/mcp-grok-bot-b8c2461e.mjs +435 -24
- package/dist/package.json +3 -3
- package/dist/plugin.json +1 -1
- package/dist/scripts/gbot-relay.mjs +138 -22
- package/dist/skills/talk-to-grok-bot/SKILL.md +18 -0
- package/package.json +3 -3
package/dist/install.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'nod
|
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
8
|
|
|
9
9
|
const pluginName = "gbot";
|
|
10
|
-
const pluginVersion = "0.
|
|
10
|
+
const pluginVersion = "0.8.0";
|
|
11
11
|
const receiptFile = ".agent-bundle-install.json";
|
|
12
12
|
const receiptFormat = "agent-bundle-install-receipt/2";
|
|
13
13
|
const legacyReceiptFormat = "agent-bundle-install-receipt/1";
|
|
@@ -118,7 +118,7 @@ const hashEntry = (hash, relative, metadata, bytes) => {
|
|
|
118
118
|
// Deterministic tree walk: symlinks and special files refused, the root receipt skipped. `transform`
|
|
119
119
|
// maps a file's bytes to what the Cursor copy will hold (the Agent Plugins mcp.json expansion below), so
|
|
120
120
|
// the artifact hash describes the installed form and reruns compare like for like.
|
|
121
|
-
const
|
|
121
|
+
const readTree = async (root, transform, selectedPaths) => {
|
|
122
122
|
const rootMetadata = await lstat(root);
|
|
123
123
|
if (rootMetadata.isSymbolicLink() || !rootMetadata.isDirectory()) throw unsupported('.');
|
|
124
124
|
const hash = createHash('sha256');
|
|
@@ -139,10 +139,11 @@ const inventory = async (root, transform) => {
|
|
|
139
139
|
const bytes = await readFile(absolute);
|
|
140
140
|
hashEntry(hash, relative, metadata, transform === undefined ? bytes : transform(posixPath, bytes));
|
|
141
141
|
};
|
|
142
|
-
if (
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
142
|
+
if (selectedPaths !== undefined) {
|
|
143
|
+
for (const file of selectedPaths) {
|
|
144
|
+
if (!(await exists(join(root, file)))) throw new Error(`bundle does not match its manifest: ${file} is missing.`);
|
|
145
|
+
await visit(file);
|
|
146
|
+
}
|
|
146
147
|
return { files, hash: hash.digest('hex') };
|
|
147
148
|
}
|
|
148
149
|
for (const entry of (await readdir(root)).sort((left, right) => left.localeCompare(right))) {
|
|
@@ -157,6 +158,13 @@ const inventory = async (root, transform) => {
|
|
|
157
158
|
}
|
|
158
159
|
return { files, hash: hash.digest('hex') };
|
|
159
160
|
};
|
|
161
|
+
const inventory = (root, transform) => readTree(root, transform, undefined);
|
|
162
|
+
const artifactInventory = async (root, transform) => {
|
|
163
|
+
if (artifactManifest === undefined) return inventory(root, transform);
|
|
164
|
+
const selected = new Set(['agent-bundle.manifest.json', ...artifactManifest.files.map((file) => file.path)]);
|
|
165
|
+
for (const file of ['.env', '.env.local']) if (await exists(join(root, file))) selected.add(file);
|
|
166
|
+
return readTree(root, transform, [...selected].sort(compareTreePaths));
|
|
167
|
+
};
|
|
160
168
|
|
|
161
169
|
const treeHash = async (root) => (await inventory(root)).hash;
|
|
162
170
|
|
|
@@ -545,7 +553,7 @@ const stage = async (tree, receiptOptions = {}) => {
|
|
|
545
553
|
};
|
|
546
554
|
await cp(source, root, { errorOnExist: true, filter, force: false, recursive: true, verbatimSymlinks: true });
|
|
547
555
|
if (expansion !== undefined) await writeFile(join(root, expansion.mcpDocument), expansion.expanded, 'utf8');
|
|
548
|
-
const staged = await
|
|
556
|
+
const staged = await artifactInventory(root);
|
|
549
557
|
await writeFile(join(root, receiptFile), receiptFor(staged, receiptOptions), 'utf8');
|
|
550
558
|
return { inventory: staged, parent, root };
|
|
551
559
|
} catch (error) {
|
|
@@ -1018,7 +1026,7 @@ const marketplaceManifestPath = join(marketplaceRepo, '.cursor-plugin', 'marketp
|
|
|
1018
1026
|
// commit lets --uninstall prove the repository is still the one staging wrote.
|
|
1019
1027
|
const writeMarketplaceReceipt = async (commit) => {
|
|
1020
1028
|
const previous = await readReceiptFile(marketplaceReceipt);
|
|
1021
|
-
const tree = await
|
|
1029
|
+
const tree = await artifactInventory(source);
|
|
1022
1030
|
if (previous !== undefined && previous.contentHash === tree.hash && previous.registrations[0]?.commit === commit) return;
|
|
1023
1031
|
await mkdir(receiptsRoot, { recursive: true });
|
|
1024
1032
|
// The committed repository is removed wholesale after a HEAD check; the receipt owns no individual files.
|
|
@@ -1081,6 +1089,7 @@ if (mode === 'marketplace') {
|
|
|
1081
1089
|
if (nestedGit !== undefined) {
|
|
1082
1090
|
throw new Error(`--mode marketplace refuses bundle-internal Git metadata at ${JSON.stringify(nestedGit)}: git would record it as an empty gitlink and Cursor would import a plugin without files. Stage from a built bundle directory without .git, or use the default local mode.`);
|
|
1083
1091
|
}
|
|
1092
|
+
await artifactInventory(source);
|
|
1084
1093
|
await mkdir(marketplaceRoot, { recursive: true });
|
|
1085
1094
|
if (await exists(marketplaceRepo)) {
|
|
1086
1095
|
let stagedVersion;
|
|
@@ -1089,6 +1098,7 @@ if (mode === 'marketplace') {
|
|
|
1089
1098
|
if (stagedVersion !== undefined && stagedVersion !== pluginVersion) {
|
|
1090
1099
|
throw new Error(`Refusing version collision at ${marketplaceRepo}: found ${stagedVersion}, requested ${pluginVersion}.`);
|
|
1091
1100
|
}
|
|
1101
|
+
// The staged plugin is an unfiltered copy of the bundle, so both sides hash the files present.
|
|
1092
1102
|
if (await exists(marketplacePlugin) && await exists(join(marketplaceRepo, '.git')) && await treeHash(source) === await treeHash(marketplacePlugin)) {
|
|
1093
1103
|
let stagedManifest;
|
|
1094
1104
|
try { stagedManifest = await readFile(marketplaceManifestPath, 'utf8'); }
|
|
@@ -1143,7 +1153,7 @@ if (mode === 'marketplace') {
|
|
|
1143
1153
|
}
|
|
1144
1154
|
|
|
1145
1155
|
// The artifact is inventoried (and any unsupported entry refused) before anything is created in the home.
|
|
1146
|
-
const artifact = await
|
|
1156
|
+
const artifact = await artifactInventory(source, cursorTransform);
|
|
1147
1157
|
// The receipt records which host directories this run creates on the way to the plugin root (a fresh Cursor
|
|
1148
1158
|
// home has no plugins/local), so --uninstall can prune exactly those and no more.
|
|
1149
1159
|
const createdHostDirectories = [];
|