bidtry-code-context 0.0.0-stage → 0.1.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/BIDTRY_TEAM_SOURCE.txt +32 -0
- package/README.md +42 -2
- package/SOURCE.json +15 -0
- package/bin/cli.mjs +24 -0
- package/lib/runtime.mjs +502 -0
- package/package.json +38 -4
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
Bidtry — Open Source Acknowledgements
|
|
2
|
+
|
|
3
|
+
Original project: Repomix
|
|
4
|
+
|
|
5
|
+
========================================================================
|
|
6
|
+
Original file: NOTICE.md
|
|
7
|
+
========================================================================
|
|
8
|
+
|
|
9
|
+
# Attribution
|
|
10
|
+
|
|
11
|
+
## Bidtry product attribution
|
|
12
|
+
|
|
13
|
+
Bidtry Code Context is the Bidtry-maintained project in this directory. Its implementation is derived from Repomix and retains compatible technical identifiers.
|
|
14
|
+
|
|
15
|
+
Original authorship, copyright notices, project license terms, and third-party licenses remain with their respective holders. Bidtry branding does not replace those notices.
|
|
16
|
+
|
|
17
|
+
Original package authors recorded before the branding update:
|
|
18
|
+
|
|
19
|
+
- "Kazuki Yamada <koukun0120@gmail.com>"
|
|
20
|
+
|
|
21
|
+
========================================================================
|
|
22
|
+
Original source: https://github.com/yamadashy/repomix/blob/main/LICENSE
|
|
23
|
+
Git blob: cc6cde3b20418ea0c9f503be0ab2e301bb02d6db
|
|
24
|
+
========================================================================
|
|
25
|
+
|
|
26
|
+
Copyright 2024 Kazuki Yamada
|
|
27
|
+
|
|
28
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
29
|
+
|
|
30
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
31
|
+
|
|
32
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,43 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Bidtry Code Context
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Brand:** Bidtry · **Developer:** Keshab Amgain
|
|
4
|
+
|
|
5
|
+
Bidtry Code Context: install project-local workflow instructions. Native engines are separate.
|
|
6
|
+
|
|
7
|
+
A workflow for repository source, configuration, and relevant tests.
|
|
8
|
+
|
|
9
|
+
## Why use it?
|
|
10
|
+
|
|
11
|
+
Large repositories contain more information than one task needs. Select the relevant source and tests, respect ignore rules, and produce context your coding agent can actually use.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
Requires Node.js 20 or newer. Open a terminal in your existing project folder, then run this command on macOS, Windows PowerShell, or Linux:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npx bidtry-code-context@0.1.1 install --target .
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The command installs and verifies workflow files under `.bidtry/skills/`. No particular coding assistant is required. Open `.bidtry/skills/bidtry-code-context/START-HERE.md`, then read the workflow in `SKILL.md`. You can follow the instructions yourself or share them with your preferred assistant.
|
|
22
|
+
|
|
23
|
+
## Preview, verify, and remove
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
npx bidtry-code-context@0.1.1 install --target . --dry-run
|
|
27
|
+
npx bidtry-code-context@0.1.1 verify --target .
|
|
28
|
+
npx bidtry-code-context@0.1.1 uninstall --target . --dry-run
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Remove `--dry-run` from the removal command only when ready. Unknown or edited files are preserved by refusing unsafe changes. Symlinked destinations are rejected.
|
|
32
|
+
|
|
33
|
+
Optional assistant integrations: pass `--agent codex`, `--agent claude`, or `--agent cursor`. These place instructions in that assistant's project skill directory. Start a new assistant session after installing. Dollar-sign and slash examples inside skill files are assistant requests, not terminal commands.
|
|
34
|
+
|
|
35
|
+
## What is included?
|
|
36
|
+
|
|
37
|
+
Workflow instructions and their supporting reference files. This npm release does not install a standalone application, native engine, compiler, browser, solver, API service, or project dependencies. Some workflow checks need separately installed native tools. They are not certified by installing these instructions. There are no npm runtime dependencies or install lifecycle scripts.
|
|
38
|
+
|
|
39
|
+
## Copyright and license texts
|
|
40
|
+
|
|
41
|
+
Original copyright notices and full license texts are included in `BIDTRY_TEAM_SOURCE.txt`. Different included materials retain their original terms. Bidtry branding does not replace original authorship.
|
|
42
|
+
|
|
43
|
+
[Tool information](https://bidtry.com/code-context)
|
package/SOURCE.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"package": "bidtry-code-context@0.1.1",
|
|
3
|
+
"artifactKind": "project-local workflow installer; native engines excluded",
|
|
4
|
+
"runtimeSha256": "8a5a2db03bee2339c0d6085242a3fbdb1988f9bb75cc191683d48394cd52e00f",
|
|
5
|
+
"bundledRuntimeSha256": "baa502f978cf630a676d1d1bacc93c0bdc09488c1ee4d0c3ca1d0d0c27a514be",
|
|
6
|
+
"payloadSha256": "ceb3d6e7650e6595adeff2ed8194800be762740c0764991d92a9e211cd9c8111",
|
|
7
|
+
"products": [
|
|
8
|
+
{
|
|
9
|
+
"name": "bidtry-code-context",
|
|
10
|
+
"version": "0.1.1",
|
|
11
|
+
"slug": "code-context"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"noticeSha256": "3616f99b015001b0c7e97bf529502adccc91cfb470b5d87ce6a81aefc7699f02"
|
|
15
|
+
}
|
package/bin/cli.mjs
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { runCli } from '../lib/runtime.mjs';
|
|
3
|
+
const product = {"name":"bidtry-code-context","title":"Bidtry Code Context","slug":"code-context","version":"0.1.1"};
|
|
4
|
+
const args = process.argv.slice(2);
|
|
5
|
+
const command = args[0];
|
|
6
|
+
const help = "\nBidtry Code Context — project workflow installer\n\nUsage:\n bidtry-code-context install [--target PATH] [--agent project|codex|claude|cursor|all] [--dry-run]\n bidtry-code-context verify [options]\n bidtry-code-context uninstall [options] [--dry-run]\n bidtry-code-context list\n\nDefault: editor-readable workflow files in .bidtry/skills/ inside your project.\nInstall verifies the managed files automatically. Requires Node.js 20 or newer.\nThis package installs workflow instructions, not native engines or application dependencies.\nOriginal copyright notices and license texts: BIDTRY_TEAM_SOURCE.txt\n";
|
|
7
|
+
try {
|
|
8
|
+
if (!command || args.includes('--help') || args.includes('-h') || command === 'help') {
|
|
9
|
+
process.stdout.write(help);
|
|
10
|
+
} else if (args.includes('--version') || args.includes('-v') || command === 'version') {
|
|
11
|
+
process.stdout.write("0.1.1" + '\n');
|
|
12
|
+
} else {
|
|
13
|
+
if (!['install', 'verify', 'uninstall', 'remove', 'list'].includes(command)) throw new Error('Unknown command. Use --help.');
|
|
14
|
+
if (product && args.some(value => /^--(?:tool|tools|preset)(?:=|$)/.test(value))) throw new Error('This package installs ' + product.name + ' only. Use @bidtry/tools to choose other tools.');
|
|
15
|
+
const options = args.slice(1);
|
|
16
|
+
if (!args.some(value => /^--agent(?:=|$)/.test(value))) options.push('--agent', 'project');
|
|
17
|
+
if (product && command !== 'list') options.push('--tool', product.slug);
|
|
18
|
+
process.stdout.write(runCli([command, ...options], process.cwd()));
|
|
19
|
+
if (command === 'install' && !args.includes('--dry-run')) process.stdout.write(runCli(['verify', ...options], process.cwd()));
|
|
20
|
+
}
|
|
21
|
+
} catch (error) {
|
|
22
|
+
process.stderr.write(error.message + '\n');
|
|
23
|
+
process.exitCode = 1;
|
|
24
|
+
}
|
package/lib/runtime.mjs
ADDED
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
3
|
+
import {
|
|
4
|
+
chmodSync,
|
|
5
|
+
existsSync,
|
|
6
|
+
lstatSync,
|
|
7
|
+
mkdirSync,
|
|
8
|
+
readFileSync,
|
|
9
|
+
readdirSync,
|
|
10
|
+
realpathSync,
|
|
11
|
+
renameSync,
|
|
12
|
+
rmdirSync,
|
|
13
|
+
unlinkSync,
|
|
14
|
+
writeFileSync
|
|
15
|
+
} from 'node:fs';
|
|
16
|
+
import path from 'node:path';
|
|
17
|
+
import { pathToFileURL } from 'node:url';
|
|
18
|
+
|
|
19
|
+
export default runCli;
|
|
20
|
+
|
|
21
|
+
const INSTALLER_VERSION = '1.1.0';
|
|
22
|
+
const PAYLOAD = JSON.parse(Buffer.from('eyJzY2hlbWFWZXJzaW9uIjoxLCJwcm9kdWN0cyI6W3sic2x1ZyI6ImNvZGUtY29udGV4dCIsIm5hbWUiOiJiaWR0cnktY29kZS1jb250ZXh0IiwidGl0bGUiOiJCaWR0cnkgQ29kZSBDb250ZXh0IiwidmVyc2lvbiI6IjAuMS4xIiwicHJpbWFyeUFjdGlvbiI6InBhY2siLCJmaWxlcyI6eyJhZ2VudHMvb3BlbmFpLnlhbWwiOnsiY29udGVudCI6ImludGVyZmFjZTpcbiAgZGlzcGxheV9uYW1lOiBcIkJpZHRyeSBDb2RlIENvbnRleHRcIlxuICBzaG9ydF9kZXNjcmlwdGlvbjogXCJCaWR0cnkgQ29kZSBDb250ZXh0IHByb2plY3Qgd29ya2Zsb3dzXCJcbiAgZGVmYXVsdF9wcm9tcHQ6IFwiVXNlICRiaWR0cnktY29kZS1jb250ZXh0IHBhY2sgc3JjIGFuZCB0aGUgcmVsZXZhbnQgdGVzdHMuXCJcbiIsIm1vZGUiOjQyMH0sIlNLSUxMLm1kIjp7ImNvbnRlbnQiOiItLS1cbm5hbWU6IGJpZHRyeS1jb2RlLWNvbnRleHRcbmRlc2NyaXB0aW9uOiBcIlBhY2thZ2UgcmVwb3NpdG9yeSBjb250ZW50cyBpbnRvIGNvbnRleHQgZmlsZXMgZm9yIEFJIHRvb2xzIGFuZCBjb2RlIHJldmlldy4gVXNlIGZvciBzcmMgYW5kIHRoZSByZWxldmFudCB0ZXN0cyBhbmQgcmVsYXRlZCBjb2RlIGNvbnRleHQgdGFza3MgaW4gYW4gZXhpc3RpbmcgbG9jYWwgcHJvamVjdC5cIlxuLS0tXG5cbiMgQmlkdHJ5IENvZGUgQ29udGV4dFxuXG5Vc2UgdGhpcyBza2lsbCBpbiB0aGUgdGFyZ2V0IHByb2plY3QuIFJlYWQgaXRzIHJlcG9zaXRvcnkgaW5zdHJ1Y3Rpb25zIGZpcnN0IGFuZCB1c2UgaXRzIGV4aXN0aW5nIGFyY2hpdGVjdHVyZSwgcGFja2FnZSBtYW5hZ2VyLCBhbmQgYXV0aG9yaXphdGlvbiBzY29wZS4gUmVhZCB0aGUgcmVsZXZhbnQgc2VjdGlvbiBvZiBCSURUUlkubWQgd2hlbiBwcmVzZW50LlxuXG4jIyBJbnZvY2F0aW9uXG5cbkluIENvZGV4LCB1c2UgYCRiaWR0cnktY29kZS1jb250ZXh0IGluaXRgLCB0aGVuIGAkYmlkdHJ5LWNvZGUtY29udGV4dCBwYWNrIHNyYyBhbmQgdGhlIHJlbGV2YW50IHRlc3RzYC4gSW4gQ2xhdWRlIENvZGUgb3IgQ3Vyc29yLCB1c2UgdGhlIGNvcnJlc3BvbmRpbmcgYC9iaWR0cnktY29kZS1jb250ZXh0YCBza2lsbCBjb21tYW5kLiBUaGVzZSBhcmUgY29kaW5nLWFnZW50IHJlcXVlc3RzLCBub3QgdGVybWluYWwgY29tbWFuZHMuXG5cbiMjIE1vZGVzXG5cbi0gYGluaXRgOiBSZWFkIHJlcG9zaXRvcnkgaW5zdHJ1Y3Rpb25zIGFuZCBhbnkgUFJPRFVDVC5tZCBvciBCSURUUlkubWQuIEVzdGFibGlzaCB0aGUgdGFyZ2V0LCB1c2VycywgY29uc3RyYWludHMsIGFuZCBhZ3JlZWQgdmVyaWZpY2F0aW9uIGNvbW1hbmRzLiBDcmVhdGUgb3IgdXBkYXRlIG9ubHkgdGhpcyB0b29s4oCZcyBzZWN0aW9uIGluIEJJRFRSWS5tZCwgcHJlc2VydmluZyBvdGhlciBjb250ZXh0IGFuZCB1c2VyIGVkaXRzLiBBc2sgb25seSBmb3IgZmFjdHMgdGhhdCBjYW5ub3QgYmUgaW5mZXJyZWQgYW5kIG1hdGVyaWFsbHkgY2hhbmdlIHRoZSB3b3JrLlxuLSBgcGFja2A6IEFwcGx5IHRoZSBkb21haW4gd29ya2Zsb3cgYmVsb3cgdG8gdGhlIHNwZWNpZmllZCB0YXJnZXQsIGtlZXBpbmcgdGhlIHVzZXLigJlzIHJlcXVlc3RlZCBvdXRjb21lIGFuZCBzY29wZS5cbi0gYGF1ZGl0YDogQXNzZXNzIHRoZSBzcGVjaWZpZWQgdGFyZ2V0IGFuZCByZXBvcnQgZXZpZGVuY2UtYmFja2VkIGZpbmRpbmdzLCB0aGVpciBpbXBhY3QsIGFuZCByZWxldmFudCB2ZXJpZmljYXRpb24gbGltaXRzLiBBbiBhdWRpdCBhbG9uZSBkb2VzIG5vdCBhdXRob3JpemUgdW5yZWxhdGVkIGZpeGVzLlxuLSBgZml4YDogSW1wbGVtZW50IHRoZSByZXF1ZXN0ZWQgY29ycmVjdGlvbiwgcHJlc2VydmUgdW5yZWxhdGVkIGJlaGF2aW9yIGFuZCBjb25maWd1cmF0aW9uLCBhbmQgdmVyaWZ5IHRoZSBhZmZlY3RlZCByZXN1bHQuXG4tIGB2ZXJpZnlgOiBSdW4gdGhlIHJlbGV2YW50IGNoZWNrcyBhZ3JlZWQgZHVyaW5nIGluaXQgd2hlbiB0aGV5IGFyZSBhdmFpbGFibGUuIFJlcG9ydCBleGFjdCByZXN1bHRzIGFuZCBibG9ja2VyczsgZG8gbm90IGZhYnJpY2F0ZSBleGVjdXRpb24gb3IgYSBwYXNzaW5nIHJlc3VsdC5cblxuV2hlbiBubyBtb2RlIGlzIHN1cHBsaWVkLCBpbmZlciB0aGUgYWN0aW9uIGZyb20gdGhlIHVzZXLigJlzIHJlcXVlc3Q7IGFzayBvbmx5IGlmIHRoZSBpbnRlbmRlZCBvdXRjb21lIGlzIGdlbnVpbmVseSBhbWJpZ3VvdXMuXG5cbiMjIERvbWFpbiB3b3JrZmxvd1xuXG4tIFNlbGVjdCB0aGUgZmlsZXMgbmVlZGVkIGZvciB0aGUgYWN0dWFsIHF1ZXN0aW9uLCBpbmNsdWRpbmcgcmVsZXZhbnQgdGVzdHMgYW5kIGNvbmZpZ3VyYXRpb247IGRvIG5vdCBpbmRpc2NyaW1pbmF0ZWx5IGV4cG9ydCB0aGUgZW50aXJlIGNoZWNrb3V0LlxuLSBSZXNwZWN0IGlnbm9yZSBydWxlcyBhbmQgZXhjbHVkZSBjcmVkZW50aWFscywgZ2VuZXJhdGVkIGRlcGVuZGVuY2llcywgYW5kIGlycmVsZXZhbnQgbGFyZ2UgYXJ0aWZhY3RzIHVubGVzcyB0aGUgdGFzayBzcGVjaWZpY2FsbHkgcmVxdWlyZXMgdGhlbS5cbi0gUmVwb3J0IHNlbGVjdGlvbiBib3VuZGFyaWVzLCBvbWlzc2lvbnMsIGFuZCBzaXplIGxpbWl0cyBzbyBkb3duc3RyZWFtIGFuYWx5c2lzIGRvZXMgbm90IHRyZWF0IGEgcGFydGlhbCBidW5kbGUgYXMgdGhlIHdob2xlIHJlcG9zaXRvcnkuXG5cbiMjIE5hdGl2ZSB0b29sIGJvdW5kYXJ5XG5cblRoZSBpbnN0YWxsZXIgYWRkcyBhZ2VudCBpbnN0cnVjdGlvbnMgb25seS4gSXQgZG9lcyBub3QgaW5zdGFsbCBvciBidW5kbGUgUmVwb21peC1jb21wYXRpYmxlIHJlcG9zaXRvcnkgcGFja2luZy4gSW5zcGVjdCB0aGUgdGFyZ2V04oCZcyBhY3R1YWwgZGVwZW5kZW5jaWVzIGFuZCBhdmFpbGFibGUgdG9vbHMgYmVmb3JlIGludm9raW5nIG5hdGl2ZSBjaGVja3MuIFVzZSB0aGUgZXhpc3RpbmcgY29tcGF0aWJsZSBuYW1lcyB3aGVuIGEgdG9vbCBpcyBhbHJlYWR5IGNvbmZpZ3VyZWQuIElmIGEgbmF0aXZlIHRvb2wgaXMgbWlzc2luZywgc3RhdGUgdGhlIHNldHVwIGdhcCBhbmQgdGhlIGxpbWl0cyBvZiBhbnkgbWFudWFsIGFuYWx5c2lzLiBEbyBub3QgZmV0Y2ggYW4gdW52ZXJpZmllZCBwcml2YXRlIEJpZHRyeSBwYWNrYWdlLCBpbnN0YWxsIGEgc2Vjb25kIGFwcGxpY2F0aW9uIGludG8gdGhlIHRhcmdldCwgb3IgcmVwb3J0IG5hdGl2ZSBjaGVja3MgYXMgZXhlY3V0ZWQgd2hlbiB0aGV5IHdlcmUgbm90LlxuIiwibW9kZSI6NDIwfX19XX0=', 'base64').toString('utf8'));
|
|
23
|
+
const AGENT_PATHS = { codex: '.agents', claude: '.claude', cursor: '.cursor', project: '.bidtry' };
|
|
24
|
+
const MANIFEST = '.bidtry-install.json';
|
|
25
|
+
const DESIGN_PRESET = [
|
|
26
|
+
'design-improve',
|
|
27
|
+
'accessibility-improve',
|
|
28
|
+
'graph-interface'
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
function digest(contents) {
|
|
32
|
+
return createHash('sha256').update(contents).digest('hex');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function assertPayload() {
|
|
36
|
+
if (PAYLOAD?.schemaVersion !== 1 || !Array.isArray(PAYLOAD.products)) {
|
|
37
|
+
throw new Error('The Bidtry installer payload is missing or invalid.');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function productMap() {
|
|
42
|
+
assertPayload();
|
|
43
|
+
return new Map(PAYLOAD.products.map(product => [product.slug, product]));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function parseValue(args, index, option) {
|
|
47
|
+
const argument = args[index];
|
|
48
|
+
const value = argument.includes('=')
|
|
49
|
+
? argument.slice(option.length + 1)
|
|
50
|
+
: args[index + 1];
|
|
51
|
+
if (!value || value.startsWith('--')) {
|
|
52
|
+
throw new Error(`Missing value for ${option}.`);
|
|
53
|
+
}
|
|
54
|
+
return { value, consumed: argument.includes('=') ? 0 : 1 };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Parse options without touching the target project. */
|
|
58
|
+
export function parseArguments(args, cwd) {
|
|
59
|
+
const knownCommands = new Set([
|
|
60
|
+
'help',
|
|
61
|
+
'version',
|
|
62
|
+
'list',
|
|
63
|
+
'install',
|
|
64
|
+
'verify',
|
|
65
|
+
'uninstall',
|
|
66
|
+
'remove'
|
|
67
|
+
]);
|
|
68
|
+
let command = 'help';
|
|
69
|
+
let agent = 'codex';
|
|
70
|
+
let target = cwd;
|
|
71
|
+
let dryRun = false;
|
|
72
|
+
let selector = null;
|
|
73
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
74
|
+
const argument = args[index];
|
|
75
|
+
if (index === 0 && knownCommands.has(argument)) {
|
|
76
|
+
command = argument === 'remove' ? 'uninstall' : argument;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (argument === '--help' || argument === '-h') {
|
|
80
|
+
command = 'help';
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (argument === '--version' || argument === '-v') {
|
|
84
|
+
command = 'version';
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (argument === '--dry-run') {
|
|
88
|
+
dryRun = true;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const option = argument.split('=', 1)[0];
|
|
92
|
+
if (!['--agent', '--target', '--tool', '--tools', '--preset'].includes(option)) {
|
|
93
|
+
throw new Error(`Unknown argument: ${argument}. Use --help for usage.`);
|
|
94
|
+
}
|
|
95
|
+
const parsed = parseValue(args, index, option);
|
|
96
|
+
index += parsed.consumed;
|
|
97
|
+
if (option === '--agent') agent = parsed.value;
|
|
98
|
+
if (option === '--target') target = parsed.value;
|
|
99
|
+
if (['--tool', '--tools', '--preset'].includes(option)) {
|
|
100
|
+
if (selector) {
|
|
101
|
+
throw new Error('Choose exactly one of --tool, --tools, or --preset.');
|
|
102
|
+
}
|
|
103
|
+
selector = { option, value: parsed.value };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (agent !== 'all' && !Object.hasOwn(AGENT_PATHS, agent)) {
|
|
107
|
+
throw new Error(
|
|
108
|
+
`Unsupported installation format: ${agent}. Choose project, codex, claude, cursor, or all.`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
if (['install', 'verify', 'uninstall'].includes(command) && !selector) {
|
|
112
|
+
throw new Error('Choose tools with --tool, --tools, or --preset.');
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
command,
|
|
116
|
+
target: path.resolve(cwd, target),
|
|
117
|
+
agents: agent === 'all' ? ['codex', 'claude', 'cursor'] : [agent],
|
|
118
|
+
dryRun,
|
|
119
|
+
selector
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function selectProducts(selector) {
|
|
124
|
+
const products = productMap();
|
|
125
|
+
let slugs;
|
|
126
|
+
if (selector.option === '--preset') {
|
|
127
|
+
if (selector.value === 'design') slugs = DESIGN_PRESET;
|
|
128
|
+
else if (selector.value === 'all') slugs = [...products.keys()].sort();
|
|
129
|
+
else throw new Error('Unsupported preset. Choose design or all.');
|
|
130
|
+
} else if (selector.option === '--tool') {
|
|
131
|
+
slugs = [selector.value];
|
|
132
|
+
} else {
|
|
133
|
+
slugs = selector.value.split(',').map(value => value.trim()).filter(Boolean);
|
|
134
|
+
}
|
|
135
|
+
if (!slugs.length) throw new Error('No tools were selected.');
|
|
136
|
+
if (new Set(slugs).size !== slugs.length) {
|
|
137
|
+
throw new Error('Tool selection contains duplicates.');
|
|
138
|
+
}
|
|
139
|
+
return slugs.map(slug => {
|
|
140
|
+
const product = products.get(slug);
|
|
141
|
+
if (!product) throw new Error(`Unknown Bidtry tool: ${slug}.`);
|
|
142
|
+
return product;
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function assertRelative(relative) {
|
|
147
|
+
if (
|
|
148
|
+
typeof relative !== 'string' ||
|
|
149
|
+
!relative ||
|
|
150
|
+
path.isAbsolute(relative) ||
|
|
151
|
+
relative.split(/[\\/]/).includes('..')
|
|
152
|
+
) {
|
|
153
|
+
throw new Error(`Invalid packaged file path: ${relative}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function assertRegularPath(root, relative) {
|
|
158
|
+
assertRelative(relative);
|
|
159
|
+
let current = root;
|
|
160
|
+
const parts = relative.split(/[\\/]/);
|
|
161
|
+
for (const [index, part] of parts.entries()) {
|
|
162
|
+
current = path.join(current, part);
|
|
163
|
+
let info;
|
|
164
|
+
try {
|
|
165
|
+
info = lstatSync(current);
|
|
166
|
+
} catch (error) {
|
|
167
|
+
if (error.code === 'ENOENT') return;
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
if (info.isSymbolicLink()) {
|
|
171
|
+
throw new Error(`Refusing to follow a symlink: ${current}`);
|
|
172
|
+
}
|
|
173
|
+
if (index < parts.length - 1 && !info.isDirectory()) {
|
|
174
|
+
throw new Error(`Expected a directory: ${current}`);
|
|
175
|
+
}
|
|
176
|
+
if (index === parts.length - 1 && !info.isFile()) {
|
|
177
|
+
throw new Error(`Expected a regular file: ${current}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function materializeFiles(product, agent) {
|
|
183
|
+
const result = {};
|
|
184
|
+
const agentSkill = `${AGENT_PATHS[agent]}/skills/bidtry-design-improve`;
|
|
185
|
+
for (const [name, file] of Object.entries(product.files)) {
|
|
186
|
+
assertRelative(name);
|
|
187
|
+
if (
|
|
188
|
+
typeof file?.content !== 'string' ||
|
|
189
|
+
![0o644, 0o755].includes(file.mode)
|
|
190
|
+
) {
|
|
191
|
+
throw new Error(`Invalid packaged skill file: ${product.slug}/${name}`);
|
|
192
|
+
}
|
|
193
|
+
let contents = file.content;
|
|
194
|
+
if (product.slug === 'design-improve') {
|
|
195
|
+
contents = contents.replaceAll(
|
|
196
|
+
'.agents/skills/bidtry-design-improve',
|
|
197
|
+
agentSkill
|
|
198
|
+
);
|
|
199
|
+
if (agent !== 'codex' && agent !== 'project') {
|
|
200
|
+
contents = contents.replaceAll(
|
|
201
|
+
'$bidtry-design-improve',
|
|
202
|
+
'/bidtry-design-improve'
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
result[name] = { contents, mode: file.mode };
|
|
207
|
+
}
|
|
208
|
+
if (agent === 'project') {
|
|
209
|
+
result['START-HERE.md'] = {
|
|
210
|
+
contents: `# ${product.title}\n\nThese are project-local workflow files. Open SKILL.md in any editor, follow the workflow yourself, or give the instructions to your coding assistant. No particular assistant is required to store or read these files.\n\nThe skill's dollar-sign and slash examples are requests for compatible assistants, not shell commands. This installation does not install a standalone application, native engine, or project dependencies.\n\nTool: https://bidtry.com/${product.slug}\n`,
|
|
211
|
+
mode: 0o644
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function readManifest(root, relative, productName, isRequired = false) {
|
|
218
|
+
assertRegularPath(root, relative);
|
|
219
|
+
const absolute = path.join(root, relative);
|
|
220
|
+
if (!existsSync(absolute)) {
|
|
221
|
+
if (isRequired) throw new Error(`Bidtry installation not found: ${absolute}`);
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
let manifest;
|
|
225
|
+
try {
|
|
226
|
+
manifest = JSON.parse(readFileSync(absolute, 'utf8'));
|
|
227
|
+
} catch {
|
|
228
|
+
throw new Error(`Invalid installer manifest: ${absolute}`);
|
|
229
|
+
}
|
|
230
|
+
if (
|
|
231
|
+
manifest?.schemaVersion !== 1 ||
|
|
232
|
+
manifest?.package !== productName ||
|
|
233
|
+
!manifest.files ||
|
|
234
|
+
typeof manifest.files !== 'object'
|
|
235
|
+
) {
|
|
236
|
+
throw new Error(`Unrecognized installer manifest: ${absolute}`);
|
|
237
|
+
}
|
|
238
|
+
return manifest;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** Validate every requested destination before any file changes. */
|
|
242
|
+
export function createInstallPlan(selected, options) {
|
|
243
|
+
const root = realpathSync(options.target);
|
|
244
|
+
if (!lstatSync(root).isDirectory()) {
|
|
245
|
+
throw new Error(`Target is not a directory: ${root}`);
|
|
246
|
+
}
|
|
247
|
+
const files = [];
|
|
248
|
+
for (const product of selected) {
|
|
249
|
+
if (!/^bidtry-[a-z0-9]+(?:-[a-z0-9]+)*$/.test(product.name)) {
|
|
250
|
+
throw new Error(`Invalid Bidtry package name: ${product.name}`);
|
|
251
|
+
}
|
|
252
|
+
for (const agent of options.agents) {
|
|
253
|
+
const skillDirectory = path.join(
|
|
254
|
+
AGENT_PATHS[agent],
|
|
255
|
+
'skills',
|
|
256
|
+
product.name
|
|
257
|
+
);
|
|
258
|
+
const manifestRelative = path.join(skillDirectory, MANIFEST);
|
|
259
|
+
const previousManifest = readManifest(
|
|
260
|
+
root,
|
|
261
|
+
manifestRelative,
|
|
262
|
+
product.name
|
|
263
|
+
);
|
|
264
|
+
const payload = materializeFiles(product, agent);
|
|
265
|
+
const hashes = {};
|
|
266
|
+
for (const [name, file] of Object.entries(payload)) {
|
|
267
|
+
const relative = path.join(skillDirectory, name);
|
|
268
|
+
assertRegularPath(root, relative);
|
|
269
|
+
const destination = path.join(root, relative);
|
|
270
|
+
const previous = existsSync(destination)
|
|
271
|
+
? readFileSync(destination, 'utf8')
|
|
272
|
+
: null;
|
|
273
|
+
if (
|
|
274
|
+
previous !== null &&
|
|
275
|
+
previous !== file.contents &&
|
|
276
|
+
previousManifest?.files?.[name] !== digest(previous)
|
|
277
|
+
) {
|
|
278
|
+
throw new Error(
|
|
279
|
+
`Preserving your existing file: ${destination}. Move or rename this skill folder before installing.`
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
hashes[name] = digest(file.contents);
|
|
283
|
+
files.push({
|
|
284
|
+
path: destination,
|
|
285
|
+
relative,
|
|
286
|
+
contents: file.contents,
|
|
287
|
+
previous,
|
|
288
|
+
mode: file.mode
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
const manifestContents =
|
|
292
|
+
JSON.stringify(
|
|
293
|
+
{
|
|
294
|
+
schemaVersion: 1,
|
|
295
|
+
package: product.name,
|
|
296
|
+
version: product.version,
|
|
297
|
+
installedBy: `bidtry-tools-installer@${INSTALLER_VERSION}`,
|
|
298
|
+
files: hashes
|
|
299
|
+
},
|
|
300
|
+
null,
|
|
301
|
+
2
|
|
302
|
+
) + '\n';
|
|
303
|
+
const manifestPath = path.join(root, manifestRelative);
|
|
304
|
+
files.push({
|
|
305
|
+
path: manifestPath,
|
|
306
|
+
relative: manifestRelative,
|
|
307
|
+
contents: manifestContents,
|
|
308
|
+
previous: existsSync(manifestPath)
|
|
309
|
+
? readFileSync(manifestPath, 'utf8')
|
|
310
|
+
: null,
|
|
311
|
+
mode: 0o644
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return { root, files, skills: selected.length * options.agents.length };
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function applyInstallPlan(plan) {
|
|
319
|
+
let changed = 0;
|
|
320
|
+
for (const file of plan.files) {
|
|
321
|
+
assertRegularPath(plan.root, file.relative);
|
|
322
|
+
const current = existsSync(file.path)
|
|
323
|
+
? readFileSync(file.path, 'utf8')
|
|
324
|
+
: null;
|
|
325
|
+
if (current !== file.previous) {
|
|
326
|
+
throw new Error(`File changed during installation: ${file.path}`);
|
|
327
|
+
}
|
|
328
|
+
const currentMode = existsSync(file.path) ? lstatSync(file.path).mode & 0o777 : null;
|
|
329
|
+
if (current === file.contents && currentMode === file.mode) continue;
|
|
330
|
+
mkdirSync(path.dirname(file.path), { recursive: true });
|
|
331
|
+
if (current !== file.contents) {
|
|
332
|
+
const temporary = `${file.path}.${randomUUID()}.tmp`;
|
|
333
|
+
try {
|
|
334
|
+
writeFileSync(temporary, file.contents, {
|
|
335
|
+
flag: 'wx',
|
|
336
|
+
mode: file.mode
|
|
337
|
+
});
|
|
338
|
+
renameSync(temporary, file.path);
|
|
339
|
+
} finally {
|
|
340
|
+
if (existsSync(temporary)) unlinkSync(temporary);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
chmodSync(file.path, file.mode);
|
|
344
|
+
changed += 1;
|
|
345
|
+
}
|
|
346
|
+
return changed;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function createVerification(selected, options) {
|
|
350
|
+
const root = realpathSync(options.target);
|
|
351
|
+
const failures = [];
|
|
352
|
+
let skills = 0;
|
|
353
|
+
for (const product of selected) {
|
|
354
|
+
for (const agent of options.agents) {
|
|
355
|
+
const skillDirectory = path.join(
|
|
356
|
+
AGENT_PATHS[agent],
|
|
357
|
+
'skills',
|
|
358
|
+
product.name
|
|
359
|
+
);
|
|
360
|
+
const manifestRelative = path.join(skillDirectory, MANIFEST);
|
|
361
|
+
const manifest = readManifest(root, manifestRelative, product.name, true);
|
|
362
|
+
const payload = materializeFiles(product, agent);
|
|
363
|
+
for (const [name, file] of Object.entries(payload)) {
|
|
364
|
+
const relative = path.join(skillDirectory, name);
|
|
365
|
+
try {
|
|
366
|
+
assertRegularPath(root, relative);
|
|
367
|
+
const absolute = path.join(root, relative);
|
|
368
|
+
if (!existsSync(absolute)) throw new Error('file is missing');
|
|
369
|
+
const actual = digest(readFileSync(absolute));
|
|
370
|
+
if (actual !== digest(file.contents)) throw new Error('file is outdated or edited');
|
|
371
|
+
if (manifest.files[name] !== actual) throw new Error('manifest hash does not match');
|
|
372
|
+
} catch (error) {
|
|
373
|
+
failures.push(`${relative}: ${error.message}`);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
skills += 1;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
if (failures.length) {
|
|
380
|
+
throw new Error(`Verification failed:\n${failures.map(item => ` ${item}`).join('\n')}`);
|
|
381
|
+
}
|
|
382
|
+
return { root, skills };
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function createUninstallPlan(selected, options) {
|
|
386
|
+
const root = realpathSync(options.target);
|
|
387
|
+
const files = [];
|
|
388
|
+
const directories = new Set();
|
|
389
|
+
for (const product of selected) {
|
|
390
|
+
for (const agent of options.agents) {
|
|
391
|
+
const skillDirectory = path.join(
|
|
392
|
+
AGENT_PATHS[agent],
|
|
393
|
+
'skills',
|
|
394
|
+
product.name
|
|
395
|
+
);
|
|
396
|
+
const manifestRelative = path.join(skillDirectory, MANIFEST);
|
|
397
|
+
const manifest = readManifest(root, manifestRelative, product.name, true);
|
|
398
|
+
for (const [name, expected] of Object.entries(manifest.files)) {
|
|
399
|
+
assertRelative(name);
|
|
400
|
+
if (!/^[a-f0-9]{64}$/.test(expected)) {
|
|
401
|
+
throw new Error(`Invalid managed-file hash: ${manifestRelative}`);
|
|
402
|
+
}
|
|
403
|
+
const relative = path.join(skillDirectory, name);
|
|
404
|
+
assertRegularPath(root, relative);
|
|
405
|
+
const absolute = path.join(root, relative);
|
|
406
|
+
if (!existsSync(absolute)) {
|
|
407
|
+
throw new Error(`Managed file is missing: ${absolute}`);
|
|
408
|
+
}
|
|
409
|
+
if (digest(readFileSync(absolute)) !== expected) {
|
|
410
|
+
throw new Error(`Preserving your edited file: ${absolute}`);
|
|
411
|
+
}
|
|
412
|
+
files.push({ path: absolute, relative });
|
|
413
|
+
let directory = path.dirname(absolute);
|
|
414
|
+
const skillRoot = path.join(root, skillDirectory);
|
|
415
|
+
while (directory.startsWith(skillRoot)) {
|
|
416
|
+
directories.add(directory);
|
|
417
|
+
if (directory === skillRoot) break;
|
|
418
|
+
directory = path.dirname(directory);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
files.push({
|
|
422
|
+
path: path.join(root, manifestRelative),
|
|
423
|
+
relative: manifestRelative
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return {
|
|
428
|
+
root,
|
|
429
|
+
files,
|
|
430
|
+
directories: [...directories].sort((a, b) => b.length - a.length),
|
|
431
|
+
skills: selected.length * options.agents.length
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
function applyUninstallPlan(plan) {
|
|
436
|
+
for (const file of plan.files) {
|
|
437
|
+
assertRegularPath(plan.root, file.relative);
|
|
438
|
+
if (existsSync(file.path)) unlinkSync(file.path);
|
|
439
|
+
}
|
|
440
|
+
for (const directory of plan.directories) {
|
|
441
|
+
if (existsSync(directory) && readdirSync(directory).length === 0) {
|
|
442
|
+
rmdirSync(directory);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function help() {
|
|
448
|
+
return `Bidtry Tools Installer ${INSTALLER_VERSION}\n\nUsage:\n node bidtry-install.mjs list\n node bidtry-install.mjs install --tool SLUG [options]\n node bidtry-install.mjs install --tools SLUG,SLUG [options]\n node bidtry-install.mjs install --preset design|all [options]\n node bidtry-install.mjs verify --tool|--tools|--preset VALUE [options]\n node bidtry-install.mjs uninstall --tool|--tools|--preset VALUE [options]\n\nOptions:\n --agent project|codex|claude|cursor|all Default: codex\n --target PATH Default: current directory\n --dry-run Show changes without writing\n\nThe installer adds project-local agent skills only, or editor-readable workflow files with --agent project. It does not change application code, install dependencies, configure credentials, or install native engines.\n`;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/** Run a complete installer command. */
|
|
452
|
+
export function runCli(args, cwd) {
|
|
453
|
+
const options = parseArguments(args, cwd);
|
|
454
|
+
if (options.command === 'help') return help();
|
|
455
|
+
if (options.command === 'version') return `bidtry-tools-installer ${INSTALLER_VERSION}\n`;
|
|
456
|
+
if (options.command === 'list') {
|
|
457
|
+
return `${[...productMap().values()]
|
|
458
|
+
.sort((a, b) => a.title.localeCompare(b.title))
|
|
459
|
+
.map(product => `${product.slug}\t${product.title}`)
|
|
460
|
+
.join('\n')}\n`;
|
|
461
|
+
}
|
|
462
|
+
const selected = selectProducts(options.selector);
|
|
463
|
+
if (options.command === 'install') {
|
|
464
|
+
const plan = createInstallPlan(selected, options);
|
|
465
|
+
if (options.dryRun) {
|
|
466
|
+
return `Dry run — no files written (${plan.skills} skills):\n${plan.files
|
|
467
|
+
.map(file => ` ${file.path}`)
|
|
468
|
+
.join('\n')}\n`;
|
|
469
|
+
}
|
|
470
|
+
const changed = applyInstallPlan(plan);
|
|
471
|
+
const first = selected[0].name;
|
|
472
|
+
if (options.agents.includes('project')) {
|
|
473
|
+
return `${changed ? 'Installed or updated' : 'Already current:'} ${plan.skills} Bidtry workflow${plan.skills === 1 ? '' : 's'} in ${plan.root}.\nOpen .bidtry/skills/${first}/START-HERE.md in your editor.\nWorkflow files only; native engines and project dependencies remain separate.\n`;
|
|
474
|
+
}
|
|
475
|
+
const invocation = options.agents.includes('codex') ? `$${first} init` : `/${first} init`;
|
|
476
|
+
return `${changed ? 'Installed or updated' : 'Already current:'} ${plan.skills} Bidtry skill${plan.skills === 1 ? '' : 's'} in ${plan.root}.\nReload your coding agent, then start with ${invocation} inside the agent.\nApplication code and dependencies were not changed. Native engines remain separate.\n`;
|
|
477
|
+
}
|
|
478
|
+
if (options.command === 'verify') {
|
|
479
|
+
const result = createVerification(selected, options);
|
|
480
|
+
return `Verified ${result.skills} current Bidtry skill${result.skills === 1 ? '' : 's'} in ${result.root}.\n`;
|
|
481
|
+
}
|
|
482
|
+
const plan = createUninstallPlan(selected, options);
|
|
483
|
+
if (options.dryRun) {
|
|
484
|
+
return `Dry run — no files removed (${plan.skills} skills):\n${plan.files
|
|
485
|
+
.map(file => ` ${file.path}`)
|
|
486
|
+
.join('\n')}\n`;
|
|
487
|
+
}
|
|
488
|
+
applyUninstallPlan(plan);
|
|
489
|
+
return `Removed ${plan.skills} managed Bidtry skill${plan.skills === 1 ? '' : 's'} from ${plan.root}. Unrelated files were preserved.\n`;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
if (
|
|
493
|
+
process.argv[1] &&
|
|
494
|
+
import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href
|
|
495
|
+
) {
|
|
496
|
+
try {
|
|
497
|
+
process.stdout.write(runCli(process.argv.slice(2), process.cwd()));
|
|
498
|
+
} catch (error) {
|
|
499
|
+
process.stderr.write(`${error.message}\n`);
|
|
500
|
+
process.exitCode = 1;
|
|
501
|
+
}
|
|
502
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bidtry-code-context",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Bidtry Code Context: install project-local workflow instructions. Native engines are separate.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "SEE LICENSE IN BIDTRY_TEAM_SOURCE.txt",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "Bidtry",
|
|
9
|
+
"url": "https://bidtry.com"
|
|
10
|
+
},
|
|
11
|
+
"contributors": [
|
|
12
|
+
{
|
|
13
|
+
"name": "Keshab Amgain"
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://bidtry.com/code-context",
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=20"
|
|
19
|
+
},
|
|
20
|
+
"bin": {
|
|
21
|
+
"bidtry-code-context": "bin/cli.mjs"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"bin/cli.mjs",
|
|
25
|
+
"lib/runtime.mjs",
|
|
26
|
+
"README.md",
|
|
27
|
+
"BIDTRY_TEAM_SOURCE.txt",
|
|
28
|
+
"SOURCE.json"
|
|
29
|
+
],
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public",
|
|
32
|
+
"registry": "https://registry.npmjs.org/"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"bidtry",
|
|
36
|
+
"developer-tools",
|
|
37
|
+
"project-workflow",
|
|
38
|
+
"code-context"
|
|
39
|
+
]
|
|
40
|
+
}
|