@staff0rd/assist 0.112.0 → 0.113.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/README.md +7 -0
- package/claude/settings.json +3 -0
- package/dist/index.js +506 -86
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -114,6 +114,13 @@ After installation, the `assist` command will be available globally. You can als
|
|
|
114
114
|
- `assist netframework in-sln <csproj>` - Check whether a .csproj is referenced by any .sln file
|
|
115
115
|
- `assist jira auth` - Authenticate with Jira via API token (saves site/email to ~/.assist/jira.json)
|
|
116
116
|
- `assist jira ac <issue-key>` - Print acceptance criteria for a Jira issue
|
|
117
|
+
- `assist ravendb auth` - Configure a named RavenDB connection (prompts for name, URL, database, op:// secret reference)
|
|
118
|
+
- `assist ravendb auth --list` - List configured RavenDB connections
|
|
119
|
+
- `assist ravendb auth --remove <name>` - Remove a configured connection
|
|
120
|
+
- `assist ravendb set-connection <name>` - Set the default connection for query/collections commands
|
|
121
|
+
- `assist ravendb query [connection] [collection]` - Query a RavenDB collection (outputs JSON to stdout)
|
|
122
|
+
- `assist ravendb query [connection] [collection] --page-size <n> --sort <field> --query <lucene> --limit <n>` - Query with options
|
|
123
|
+
- `assist ravendb collections [connection]` - List collections and document counts in a database
|
|
117
124
|
- `assist complexity <pattern>` - Analyze a file (all metrics if single match, maintainability if multiple)
|
|
118
125
|
- `assist complexity cyclomatic [pattern]` - Calculate cyclomatic complexity per function
|
|
119
126
|
- `assist complexity halstead [pattern]` - Calculate Halstead metrics per function
|
package/claude/settings.json
CHANGED
|
@@ -40,6 +40,9 @@
|
|
|
40
40
|
"Bash(assist jira auth:*)",
|
|
41
41
|
"Bash(assist jira ac:*)",
|
|
42
42
|
"Bash(assist netframework:*)",
|
|
43
|
+
"Bash(assist ravendb query:*)",
|
|
44
|
+
"Bash(assist ravendb collections:*)",
|
|
45
|
+
"Bash(assist ravendb auth --list:*)",
|
|
43
46
|
"Bash(head:*)",
|
|
44
47
|
"Bash(tail:*)",
|
|
45
48
|
"Bash(grep:*)",
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.113.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -162,6 +162,17 @@ var assistConfigSchema = z.strictObject({
|
|
|
162
162
|
news: z.strictObject({
|
|
163
163
|
feeds: z.array(z.string()).default([])
|
|
164
164
|
}).default({ feeds: [] }),
|
|
165
|
+
ravendb: z.strictObject({
|
|
166
|
+
connections: z.array(
|
|
167
|
+
z.strictObject({
|
|
168
|
+
name: z.string(),
|
|
169
|
+
url: z.string(),
|
|
170
|
+
database: z.string(),
|
|
171
|
+
apiKeyRef: z.string()
|
|
172
|
+
})
|
|
173
|
+
).default([]),
|
|
174
|
+
defaultConnection: z.string().optional()
|
|
175
|
+
}).optional(),
|
|
165
176
|
voice: z.strictObject({
|
|
166
177
|
wakeWords: z.array(z.string()).default(DEFAULT_WAKE_WORDS),
|
|
167
178
|
mic: z.string().optional(),
|
|
@@ -4543,13 +4554,13 @@ function saveJson(filename, data) {
|
|
|
4543
4554
|
// src/commands/jira/jiraAuth.ts
|
|
4544
4555
|
var CONFIG_FILE = "jira.json";
|
|
4545
4556
|
async function promptCredentials(config) {
|
|
4546
|
-
const { Input, Password } = Enquirer;
|
|
4547
|
-
const site = await new
|
|
4557
|
+
const { Input: Input2, Password } = Enquirer;
|
|
4558
|
+
const site = await new Input2({
|
|
4548
4559
|
name: "site",
|
|
4549
4560
|
message: "Jira site (e.g., mycompany.atlassian.net):",
|
|
4550
4561
|
initial: config.site
|
|
4551
4562
|
}).run();
|
|
4552
|
-
const email = await new
|
|
4563
|
+
const email = await new Input2({
|
|
4553
4564
|
name: "email",
|
|
4554
4565
|
message: "Email:",
|
|
4555
4566
|
initial: config.email
|
|
@@ -5631,12 +5642,420 @@ function registerPrs(program2) {
|
|
|
5631
5642
|
});
|
|
5632
5643
|
}
|
|
5633
5644
|
|
|
5645
|
+
// src/commands/ravendb/ravendbAuth.ts
|
|
5646
|
+
import chalk60 from "chalk";
|
|
5647
|
+
|
|
5648
|
+
// src/commands/ravendb/loadConnections.ts
|
|
5649
|
+
function loadConnections() {
|
|
5650
|
+
const raw = loadGlobalConfigRaw();
|
|
5651
|
+
const ravendb = raw.ravendb;
|
|
5652
|
+
return ravendb?.connections ?? [];
|
|
5653
|
+
}
|
|
5654
|
+
function saveConnections(connections) {
|
|
5655
|
+
const raw = loadGlobalConfigRaw();
|
|
5656
|
+
const ravendb = raw.ravendb ?? {};
|
|
5657
|
+
ravendb.connections = connections;
|
|
5658
|
+
raw.ravendb = ravendb;
|
|
5659
|
+
saveGlobalConfig(raw);
|
|
5660
|
+
}
|
|
5661
|
+
|
|
5662
|
+
// src/commands/ravendb/promptConnection.ts
|
|
5663
|
+
import chalk58 from "chalk";
|
|
5664
|
+
import Enquirer3 from "enquirer";
|
|
5665
|
+
|
|
5666
|
+
// src/commands/ravendb/selectOpSecret.ts
|
|
5667
|
+
import chalk57 from "chalk";
|
|
5668
|
+
import Enquirer2 from "enquirer";
|
|
5669
|
+
|
|
5670
|
+
// src/commands/ravendb/searchItems.ts
|
|
5671
|
+
import { execSync as execSync29 } from "child_process";
|
|
5672
|
+
import chalk56 from "chalk";
|
|
5673
|
+
function opExec(args) {
|
|
5674
|
+
return execSync29(`op ${args}`, {
|
|
5675
|
+
encoding: "utf-8",
|
|
5676
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
5677
|
+
}).trim();
|
|
5678
|
+
}
|
|
5679
|
+
function searchItems(search) {
|
|
5680
|
+
let items;
|
|
5681
|
+
try {
|
|
5682
|
+
items = JSON.parse(opExec("item list --format=json"));
|
|
5683
|
+
} catch {
|
|
5684
|
+
console.error(
|
|
5685
|
+
chalk56.red(
|
|
5686
|
+
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
5687
|
+
)
|
|
5688
|
+
);
|
|
5689
|
+
process.exit(1);
|
|
5690
|
+
}
|
|
5691
|
+
const lower = search.toLowerCase();
|
|
5692
|
+
return items.filter((i) => i.title.toLowerCase().includes(lower));
|
|
5693
|
+
}
|
|
5694
|
+
function getItemFields(itemId) {
|
|
5695
|
+
try {
|
|
5696
|
+
const item = JSON.parse(opExec(`item get "${itemId}" --format=json`));
|
|
5697
|
+
return item.fields.filter((f) => f.reference && f.label);
|
|
5698
|
+
} catch {
|
|
5699
|
+
console.error(chalk56.red("Failed to get item details from 1Password."));
|
|
5700
|
+
process.exit(1);
|
|
5701
|
+
}
|
|
5702
|
+
}
|
|
5703
|
+
|
|
5704
|
+
// src/commands/ravendb/selectOpSecret.ts
|
|
5705
|
+
var { Input, Select } = Enquirer2;
|
|
5706
|
+
async function selectOne(message, choices) {
|
|
5707
|
+
if (choices.length === 1) return choices[0].value;
|
|
5708
|
+
const selected = await new Select({ name: "choice", message, choices }).run();
|
|
5709
|
+
return choices.find((c) => c.name === selected)?.value ?? selected;
|
|
5710
|
+
}
|
|
5711
|
+
async function selectOpSecret(searchTerm) {
|
|
5712
|
+
const search = searchTerm ?? await new Input({
|
|
5713
|
+
name: "search",
|
|
5714
|
+
message: "Search 1Password for API key item:"
|
|
5715
|
+
}).run();
|
|
5716
|
+
const items = searchItems(search);
|
|
5717
|
+
if (items.length === 0) {
|
|
5718
|
+
console.error(chalk57.red(`No items found matching "${search}".`));
|
|
5719
|
+
process.exit(1);
|
|
5720
|
+
}
|
|
5721
|
+
const itemId = await selectOne(
|
|
5722
|
+
"Select item:",
|
|
5723
|
+
items.map((i) => ({ name: `${i.title} (${i.vault.name})`, value: i.id }))
|
|
5724
|
+
);
|
|
5725
|
+
const fields = getItemFields(itemId);
|
|
5726
|
+
if (fields.length === 0) {
|
|
5727
|
+
console.error(chalk57.red("No fields with references found on this item."));
|
|
5728
|
+
process.exit(1);
|
|
5729
|
+
}
|
|
5730
|
+
const ref = await selectOne(
|
|
5731
|
+
"Select field:",
|
|
5732
|
+
fields.map((f) => ({ name: f.label, value: f.reference }))
|
|
5733
|
+
);
|
|
5734
|
+
return ref;
|
|
5735
|
+
}
|
|
5736
|
+
|
|
5737
|
+
// src/commands/ravendb/promptConnection.ts
|
|
5738
|
+
async function promptConnection(existingNames) {
|
|
5739
|
+
const { Input: Input2 } = Enquirer3;
|
|
5740
|
+
const name = await new Input2({
|
|
5741
|
+
name: "name",
|
|
5742
|
+
message: "Connection name:"
|
|
5743
|
+
}).run();
|
|
5744
|
+
if (existingNames.includes(name)) {
|
|
5745
|
+
console.error(chalk58.red(`Connection "${name}" already exists.`));
|
|
5746
|
+
process.exit(1);
|
|
5747
|
+
}
|
|
5748
|
+
const url = await new Input2({
|
|
5749
|
+
name: "url",
|
|
5750
|
+
message: "RavenDB base URL (e.g. https://host.ravenhq.com):"
|
|
5751
|
+
}).run();
|
|
5752
|
+
const database = await new Input2({
|
|
5753
|
+
name: "database",
|
|
5754
|
+
message: "Database name:"
|
|
5755
|
+
}).run();
|
|
5756
|
+
if (!name || !url || !database) {
|
|
5757
|
+
console.error(chalk58.red("All fields are required."));
|
|
5758
|
+
process.exit(1);
|
|
5759
|
+
}
|
|
5760
|
+
const apiKeyRef = await selectOpSecret();
|
|
5761
|
+
console.log(chalk58.dim(`Using: ${apiKeyRef}`));
|
|
5762
|
+
return { name, url, database, apiKeyRef };
|
|
5763
|
+
}
|
|
5764
|
+
|
|
5765
|
+
// src/commands/ravendb/ravendbSetConnection.ts
|
|
5766
|
+
import chalk59 from "chalk";
|
|
5767
|
+
function ravendbSetConnection(name) {
|
|
5768
|
+
const raw = loadGlobalConfigRaw();
|
|
5769
|
+
const ravendb = raw.ravendb ?? {};
|
|
5770
|
+
const connections = ravendb.connections ?? [];
|
|
5771
|
+
if (!connections.some((c) => c.name === name)) {
|
|
5772
|
+
console.error(chalk59.red(`Connection "${name}" not found.`));
|
|
5773
|
+
console.error(
|
|
5774
|
+
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
5775
|
+
);
|
|
5776
|
+
process.exit(1);
|
|
5777
|
+
}
|
|
5778
|
+
ravendb.defaultConnection = name;
|
|
5779
|
+
raw.ravendb = ravendb;
|
|
5780
|
+
saveGlobalConfig(raw);
|
|
5781
|
+
console.log(`Default connection set to "${name}".`);
|
|
5782
|
+
}
|
|
5783
|
+
|
|
5784
|
+
// src/commands/ravendb/ravendbAuth.ts
|
|
5785
|
+
async function ravendbAuth(options2) {
|
|
5786
|
+
const connections = loadConnections();
|
|
5787
|
+
if (options2.list) {
|
|
5788
|
+
if (connections.length === 0) {
|
|
5789
|
+
console.log("No RavenDB connections configured.");
|
|
5790
|
+
return;
|
|
5791
|
+
}
|
|
5792
|
+
for (const c of connections) {
|
|
5793
|
+
console.log(
|
|
5794
|
+
`${chalk60.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`
|
|
5795
|
+
);
|
|
5796
|
+
}
|
|
5797
|
+
return;
|
|
5798
|
+
}
|
|
5799
|
+
if (options2.remove) {
|
|
5800
|
+
const filtered = connections.filter((c) => c.name !== options2.remove);
|
|
5801
|
+
if (filtered.length === connections.length) {
|
|
5802
|
+
console.error(chalk60.red(`Connection "${options2.remove}" not found.`));
|
|
5803
|
+
process.exit(1);
|
|
5804
|
+
}
|
|
5805
|
+
saveConnections(filtered);
|
|
5806
|
+
console.log(`Removed connection "${options2.remove}".`);
|
|
5807
|
+
return;
|
|
5808
|
+
}
|
|
5809
|
+
const isFirst = connections.length === 0;
|
|
5810
|
+
const newConnection = await promptConnection(connections.map((c) => c.name));
|
|
5811
|
+
connections.push(newConnection);
|
|
5812
|
+
saveConnections(connections);
|
|
5813
|
+
if (isFirst) {
|
|
5814
|
+
ravendbSetConnection(newConnection.name);
|
|
5815
|
+
}
|
|
5816
|
+
console.log(`Connection "${newConnection.name}" saved.`);
|
|
5817
|
+
}
|
|
5818
|
+
|
|
5819
|
+
// src/commands/ravendb/ravendbCollections.ts
|
|
5820
|
+
import chalk64 from "chalk";
|
|
5821
|
+
|
|
5822
|
+
// src/commands/ravendb/ravenFetch.ts
|
|
5823
|
+
import chalk62 from "chalk";
|
|
5824
|
+
|
|
5825
|
+
// src/commands/ravendb/getAccessToken.ts
|
|
5826
|
+
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
5827
|
+
var TOKEN_CACHE_MS = 50 * 60 * 1e3;
|
|
5828
|
+
var tokenCache = /* @__PURE__ */ new Map();
|
|
5829
|
+
function clearCachedToken(apiKey) {
|
|
5830
|
+
tokenCache.delete(apiKey);
|
|
5831
|
+
}
|
|
5832
|
+
async function getAccessToken(apiKey) {
|
|
5833
|
+
const now = Date.now();
|
|
5834
|
+
const cached2 = tokenCache.get(apiKey);
|
|
5835
|
+
if (cached2 && now < cached2.expiry) {
|
|
5836
|
+
return cached2.token;
|
|
5837
|
+
}
|
|
5838
|
+
const response = await fetch(OAUTH_URL, {
|
|
5839
|
+
method: "GET",
|
|
5840
|
+
headers: {
|
|
5841
|
+
"Api-Key": apiKey,
|
|
5842
|
+
grant_type: "client_credentials"
|
|
5843
|
+
}
|
|
5844
|
+
});
|
|
5845
|
+
if (!response.ok) {
|
|
5846
|
+
const errorText = await response.text();
|
|
5847
|
+
throw new Error(
|
|
5848
|
+
`Failed to get access token: ${response.status} ${response.statusText}
|
|
5849
|
+
${errorText}`
|
|
5850
|
+
);
|
|
5851
|
+
}
|
|
5852
|
+
const tokenData = await response.json();
|
|
5853
|
+
const token = JSON.stringify(tokenData);
|
|
5854
|
+
tokenCache.set(apiKey, { token, expiry: now + TOKEN_CACHE_MS });
|
|
5855
|
+
return token;
|
|
5856
|
+
}
|
|
5857
|
+
|
|
5858
|
+
// src/commands/ravendb/resolveOpSecret.ts
|
|
5859
|
+
import { execSync as execSync30 } from "child_process";
|
|
5860
|
+
import chalk61 from "chalk";
|
|
5861
|
+
function resolveOpSecret(reference) {
|
|
5862
|
+
if (!reference.startsWith("op://")) {
|
|
5863
|
+
console.error(chalk61.red(`Invalid secret reference: must start with op://`));
|
|
5864
|
+
process.exit(1);
|
|
5865
|
+
}
|
|
5866
|
+
try {
|
|
5867
|
+
return execSync30(`op read "${reference}"`, {
|
|
5868
|
+
encoding: "utf-8",
|
|
5869
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
5870
|
+
}).trim();
|
|
5871
|
+
} catch {
|
|
5872
|
+
console.error(
|
|
5873
|
+
chalk61.red(
|
|
5874
|
+
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
5875
|
+
)
|
|
5876
|
+
);
|
|
5877
|
+
process.exit(1);
|
|
5878
|
+
}
|
|
5879
|
+
}
|
|
5880
|
+
|
|
5881
|
+
// src/commands/ravendb/ravenFetch.ts
|
|
5882
|
+
async function ravenFetch(connection, path42) {
|
|
5883
|
+
const apiKey = resolveOpSecret(connection.apiKeyRef);
|
|
5884
|
+
let accessToken = await getAccessToken(apiKey);
|
|
5885
|
+
const url = `${connection.url}${path42}`;
|
|
5886
|
+
const headers = {
|
|
5887
|
+
Authorization: `Bearer ${accessToken}`,
|
|
5888
|
+
"Content-Type": "application/json"
|
|
5889
|
+
};
|
|
5890
|
+
let response = await fetch(url, { headers });
|
|
5891
|
+
if (response.status === 401) {
|
|
5892
|
+
clearCachedToken(apiKey);
|
|
5893
|
+
accessToken = await getAccessToken(apiKey);
|
|
5894
|
+
headers.Authorization = `Bearer ${accessToken}`;
|
|
5895
|
+
response = await fetch(url, { headers });
|
|
5896
|
+
}
|
|
5897
|
+
if (!response.ok) {
|
|
5898
|
+
const body = await response.text();
|
|
5899
|
+
console.error(
|
|
5900
|
+
chalk62.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
5901
|
+
);
|
|
5902
|
+
console.error(body.substring(0, 500));
|
|
5903
|
+
process.exit(1);
|
|
5904
|
+
}
|
|
5905
|
+
return response.json();
|
|
5906
|
+
}
|
|
5907
|
+
|
|
5908
|
+
// src/commands/ravendb/resolveConnection.ts
|
|
5909
|
+
import chalk63 from "chalk";
|
|
5910
|
+
function loadRavendb() {
|
|
5911
|
+
const raw = loadGlobalConfigRaw();
|
|
5912
|
+
const ravendb = raw.ravendb;
|
|
5913
|
+
return {
|
|
5914
|
+
connections: ravendb?.connections ?? [],
|
|
5915
|
+
defaultConnection: ravendb?.defaultConnection
|
|
5916
|
+
};
|
|
5917
|
+
}
|
|
5918
|
+
function resolveConnection(name) {
|
|
5919
|
+
const { connections, defaultConnection } = loadRavendb();
|
|
5920
|
+
const connectionName = name ?? defaultConnection;
|
|
5921
|
+
if (!connectionName) {
|
|
5922
|
+
console.error(
|
|
5923
|
+
chalk63.red(
|
|
5924
|
+
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
5925
|
+
)
|
|
5926
|
+
);
|
|
5927
|
+
process.exit(1);
|
|
5928
|
+
}
|
|
5929
|
+
const connection = connections.find((c) => c.name === connectionName);
|
|
5930
|
+
if (!connection) {
|
|
5931
|
+
console.error(chalk63.red(`Connection "${connectionName}" not found.`));
|
|
5932
|
+
console.error(
|
|
5933
|
+
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
5934
|
+
);
|
|
5935
|
+
console.error("Run assist ravendb auth to add a connection.");
|
|
5936
|
+
process.exit(1);
|
|
5937
|
+
}
|
|
5938
|
+
return connection;
|
|
5939
|
+
}
|
|
5940
|
+
function resolveArgs(first, second) {
|
|
5941
|
+
const { connections } = loadRavendb();
|
|
5942
|
+
const isConnection = first && connections.some((c) => c.name === first);
|
|
5943
|
+
if (isConnection) {
|
|
5944
|
+
return { connection: resolveConnection(first), collection: second };
|
|
5945
|
+
}
|
|
5946
|
+
return { connection: resolveConnection(void 0), collection: first };
|
|
5947
|
+
}
|
|
5948
|
+
|
|
5949
|
+
// src/commands/ravendb/ravendbCollections.ts
|
|
5950
|
+
async function ravendbCollections(connectionName) {
|
|
5951
|
+
const connection = resolveConnection(connectionName);
|
|
5952
|
+
const data = await ravenFetch(
|
|
5953
|
+
connection,
|
|
5954
|
+
`/databases/${encodeURIComponent(connection.database)}/collections/stats`
|
|
5955
|
+
);
|
|
5956
|
+
const collections = data.Collections ?? [];
|
|
5957
|
+
if (collections.length === 0) {
|
|
5958
|
+
console.log("No collections found.");
|
|
5959
|
+
return;
|
|
5960
|
+
}
|
|
5961
|
+
for (const c of collections) {
|
|
5962
|
+
console.log(`${chalk64.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
5963
|
+
}
|
|
5964
|
+
}
|
|
5965
|
+
|
|
5966
|
+
// src/commands/ravendb/ravendbQuery.ts
|
|
5967
|
+
import chalk66 from "chalk";
|
|
5968
|
+
|
|
5969
|
+
// src/commands/ravendb/fetchAllPages.ts
|
|
5970
|
+
import chalk65 from "chalk";
|
|
5971
|
+
|
|
5972
|
+
// src/commands/ravendb/buildQueryPath.ts
|
|
5973
|
+
function buildQueryPath(opts) {
|
|
5974
|
+
const db = encodeURIComponent(opts.db);
|
|
5975
|
+
let path42;
|
|
5976
|
+
if (opts.collection) {
|
|
5977
|
+
path42 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
|
|
5978
|
+
} else {
|
|
5979
|
+
path42 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
|
|
5980
|
+
}
|
|
5981
|
+
if (opts.query) {
|
|
5982
|
+
path42 += `&query=${encodeURIComponent(opts.query)}`;
|
|
5983
|
+
}
|
|
5984
|
+
return path42;
|
|
5985
|
+
}
|
|
5986
|
+
|
|
5987
|
+
// src/commands/ravendb/fetchAllPages.ts
|
|
5988
|
+
async function fetchAllPages(connection, opts) {
|
|
5989
|
+
const allResults = [];
|
|
5990
|
+
let start3 = 0;
|
|
5991
|
+
while (true) {
|
|
5992
|
+
const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
|
|
5993
|
+
const path42 = buildQueryPath({
|
|
5994
|
+
db: connection.database,
|
|
5995
|
+
collection: opts.collection,
|
|
5996
|
+
start: start3,
|
|
5997
|
+
pageSize: effectivePageSize,
|
|
5998
|
+
sort: opts.sort,
|
|
5999
|
+
query: opts.query
|
|
6000
|
+
});
|
|
6001
|
+
const data = await ravenFetch(connection, path42);
|
|
6002
|
+
const results = data.Results ?? [];
|
|
6003
|
+
const totalResults = data.TotalResults ?? 0;
|
|
6004
|
+
if (results.length === 0) break;
|
|
6005
|
+
allResults.push(...results);
|
|
6006
|
+
start3 += results.length;
|
|
6007
|
+
process.stderr.write(
|
|
6008
|
+
`\r${chalk65.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
6009
|
+
);
|
|
6010
|
+
if (start3 >= totalResults) break;
|
|
6011
|
+
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
6012
|
+
}
|
|
6013
|
+
if (allResults.length > 0) {
|
|
6014
|
+
process.stderr.write("\n");
|
|
6015
|
+
}
|
|
6016
|
+
return allResults;
|
|
6017
|
+
}
|
|
6018
|
+
|
|
6019
|
+
// src/commands/ravendb/ravendbQuery.ts
|
|
6020
|
+
async function ravendbQuery(connectionName, collection, options2) {
|
|
6021
|
+
const resolved = resolveArgs(connectionName, collection);
|
|
6022
|
+
if (!resolved.collection && !options2.query) {
|
|
6023
|
+
console.error(chalk66.red("Provide a collection name or --query filter."));
|
|
6024
|
+
process.exit(1);
|
|
6025
|
+
}
|
|
6026
|
+
const { collection: col } = resolved;
|
|
6027
|
+
const connection = resolved.connection;
|
|
6028
|
+
const allResults = await fetchAllPages(connection, {
|
|
6029
|
+
collection: col,
|
|
6030
|
+
pageSize: Number.parseInt(options2.pageSize ?? "25", 10),
|
|
6031
|
+
sort: options2.sort ?? "-@metadata.Last-Modified",
|
|
6032
|
+
query: options2.query,
|
|
6033
|
+
limit: options2.limit ? Number.parseInt(options2.limit, 10) : void 0
|
|
6034
|
+
});
|
|
6035
|
+
console.log(JSON.stringify(allResults, null, 2));
|
|
6036
|
+
}
|
|
6037
|
+
|
|
6038
|
+
// src/commands/registerRavendb.ts
|
|
6039
|
+
function registerRavendb(program2) {
|
|
6040
|
+
const cmd = program2.command("ravendb").description("RavenDB query utilities");
|
|
6041
|
+
cmd.command("auth").description("Configure a named RavenDB connection").option("--list", "List configured connections").option("--remove <name>", "Remove a configured connection").action((options2) => ravendbAuth(options2));
|
|
6042
|
+
cmd.command("set-connection <name>").description("Set the default connection").action((name) => ravendbSetConnection(name));
|
|
6043
|
+
cmd.command("query [connection] [collection]").description("Query a RavenDB collection").option("--page-size <n>", "Documents per page", "25").option(
|
|
6044
|
+
"--sort <field>",
|
|
6045
|
+
"Sort field (prefix - for descending)",
|
|
6046
|
+
"-@metadata.Last-Modified"
|
|
6047
|
+
).option("--query <lucene>", "Lucene filter query").option("--limit <n>", "Max total documents to fetch").action(
|
|
6048
|
+
(connection, collection, options2) => ravendbQuery(connection, collection, options2)
|
|
6049
|
+
);
|
|
6050
|
+
cmd.command("collections [connection]").description("List collections in a RavenDB database").action((connection) => ravendbCollections(connection));
|
|
6051
|
+
}
|
|
6052
|
+
|
|
5634
6053
|
// src/commands/refactor/check/index.ts
|
|
5635
6054
|
import { spawn as spawn3 } from "child_process";
|
|
5636
6055
|
import * as path25 from "path";
|
|
5637
6056
|
|
|
5638
6057
|
// src/commands/refactor/logViolations.ts
|
|
5639
|
-
import
|
|
6058
|
+
import chalk67 from "chalk";
|
|
5640
6059
|
var DEFAULT_MAX_LINES = 100;
|
|
5641
6060
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
5642
6061
|
if (violations.length === 0) {
|
|
@@ -5645,43 +6064,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
5645
6064
|
}
|
|
5646
6065
|
return;
|
|
5647
6066
|
}
|
|
5648
|
-
console.error(
|
|
6067
|
+
console.error(chalk67.red(`
|
|
5649
6068
|
Refactor check failed:
|
|
5650
6069
|
`));
|
|
5651
|
-
console.error(
|
|
6070
|
+
console.error(chalk67.red(` The following files exceed ${maxLines} lines:
|
|
5652
6071
|
`));
|
|
5653
6072
|
for (const violation of violations) {
|
|
5654
|
-
console.error(
|
|
6073
|
+
console.error(chalk67.red(` ${violation.file} (${violation.lines} lines)`));
|
|
5655
6074
|
}
|
|
5656
6075
|
console.error(
|
|
5657
|
-
|
|
6076
|
+
chalk67.yellow(
|
|
5658
6077
|
`
|
|
5659
6078
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
5660
6079
|
way to refactor it, ignore it with:
|
|
5661
6080
|
`
|
|
5662
6081
|
)
|
|
5663
6082
|
);
|
|
5664
|
-
console.error(
|
|
6083
|
+
console.error(chalk67.gray(` assist refactor ignore <file>
|
|
5665
6084
|
`));
|
|
5666
6085
|
if (process.env.CLAUDECODE) {
|
|
5667
|
-
console.error(
|
|
6086
|
+
console.error(chalk67.cyan(`
|
|
5668
6087
|
## Extracting Code to New Files
|
|
5669
6088
|
`));
|
|
5670
6089
|
console.error(
|
|
5671
|
-
|
|
6090
|
+
chalk67.cyan(
|
|
5672
6091
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
5673
6092
|
`
|
|
5674
6093
|
)
|
|
5675
6094
|
);
|
|
5676
6095
|
console.error(
|
|
5677
|
-
|
|
6096
|
+
chalk67.cyan(
|
|
5678
6097
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
5679
6098
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
5680
6099
|
`
|
|
5681
6100
|
)
|
|
5682
6101
|
);
|
|
5683
6102
|
console.error(
|
|
5684
|
-
|
|
6103
|
+
chalk67.cyan(
|
|
5685
6104
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
5686
6105
|
domains, move it to a common/shared folder.
|
|
5687
6106
|
`
|
|
@@ -5691,7 +6110,7 @@ Refactor check failed:
|
|
|
5691
6110
|
}
|
|
5692
6111
|
|
|
5693
6112
|
// src/commands/refactor/check/getViolations/index.ts
|
|
5694
|
-
import { execSync as
|
|
6113
|
+
import { execSync as execSync31 } from "child_process";
|
|
5695
6114
|
import fs16 from "fs";
|
|
5696
6115
|
import { minimatch as minimatch4 } from "minimatch";
|
|
5697
6116
|
|
|
@@ -5741,7 +6160,7 @@ function getGitFiles(options2) {
|
|
|
5741
6160
|
}
|
|
5742
6161
|
const files = /* @__PURE__ */ new Set();
|
|
5743
6162
|
if (options2.staged || options2.modified) {
|
|
5744
|
-
const staged =
|
|
6163
|
+
const staged = execSync31("git diff --cached --name-only", {
|
|
5745
6164
|
encoding: "utf-8"
|
|
5746
6165
|
});
|
|
5747
6166
|
for (const file of staged.trim().split("\n").filter(Boolean)) {
|
|
@@ -5749,7 +6168,7 @@ function getGitFiles(options2) {
|
|
|
5749
6168
|
}
|
|
5750
6169
|
}
|
|
5751
6170
|
if (options2.unstaged || options2.modified) {
|
|
5752
|
-
const unstaged =
|
|
6171
|
+
const unstaged = execSync31("git diff --name-only", { encoding: "utf-8" });
|
|
5753
6172
|
for (const file of unstaged.trim().split("\n").filter(Boolean)) {
|
|
5754
6173
|
files.add(file);
|
|
5755
6174
|
}
|
|
@@ -5837,11 +6256,11 @@ async function check(pattern2, options2) {
|
|
|
5837
6256
|
|
|
5838
6257
|
// src/commands/refactor/ignore.ts
|
|
5839
6258
|
import fs17 from "fs";
|
|
5840
|
-
import
|
|
6259
|
+
import chalk68 from "chalk";
|
|
5841
6260
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
5842
6261
|
function ignore(file) {
|
|
5843
6262
|
if (!fs17.existsSync(file)) {
|
|
5844
|
-
console.error(
|
|
6263
|
+
console.error(chalk68.red(`Error: File does not exist: ${file}`));
|
|
5845
6264
|
process.exit(1);
|
|
5846
6265
|
}
|
|
5847
6266
|
const content = fs17.readFileSync(file, "utf-8");
|
|
@@ -5857,7 +6276,7 @@ function ignore(file) {
|
|
|
5857
6276
|
fs17.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
5858
6277
|
}
|
|
5859
6278
|
console.log(
|
|
5860
|
-
|
|
6279
|
+
chalk68.green(
|
|
5861
6280
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
5862
6281
|
)
|
|
5863
6282
|
);
|
|
@@ -5865,7 +6284,7 @@ function ignore(file) {
|
|
|
5865
6284
|
|
|
5866
6285
|
// src/commands/refactor/rename/index.ts
|
|
5867
6286
|
import path26 from "path";
|
|
5868
|
-
import
|
|
6287
|
+
import chalk69 from "chalk";
|
|
5869
6288
|
import { Project as Project2 } from "ts-morph";
|
|
5870
6289
|
async function rename(source, destination, options2 = {}) {
|
|
5871
6290
|
const sourcePath = path26.resolve(source);
|
|
@@ -5878,22 +6297,22 @@ async function rename(source, destination, options2 = {}) {
|
|
|
5878
6297
|
});
|
|
5879
6298
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
5880
6299
|
if (!sourceFile) {
|
|
5881
|
-
console.log(
|
|
6300
|
+
console.log(chalk69.red(`File not found in project: ${source}`));
|
|
5882
6301
|
process.exit(1);
|
|
5883
6302
|
}
|
|
5884
|
-
console.log(
|
|
6303
|
+
console.log(chalk69.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
5885
6304
|
if (options2.apply) {
|
|
5886
6305
|
sourceFile.move(destPath);
|
|
5887
6306
|
await project.save();
|
|
5888
|
-
console.log(
|
|
6307
|
+
console.log(chalk69.green("Done"));
|
|
5889
6308
|
} else {
|
|
5890
|
-
console.log(
|
|
6309
|
+
console.log(chalk69.dim("Dry run. Use --apply to execute."));
|
|
5891
6310
|
}
|
|
5892
6311
|
}
|
|
5893
6312
|
|
|
5894
6313
|
// src/commands/refactor/renameSymbol/index.ts
|
|
5895
6314
|
import path28 from "path";
|
|
5896
|
-
import
|
|
6315
|
+
import chalk70 from "chalk";
|
|
5897
6316
|
import { Project as Project3 } from "ts-morph";
|
|
5898
6317
|
|
|
5899
6318
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
@@ -5942,38 +6361,38 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
5942
6361
|
const project = new Project3({ tsConfigFilePath: tsConfigPath });
|
|
5943
6362
|
const sourceFile = project.getSourceFile(filePath);
|
|
5944
6363
|
if (!sourceFile) {
|
|
5945
|
-
console.log(
|
|
6364
|
+
console.log(chalk70.red(`File not found in project: ${file}`));
|
|
5946
6365
|
process.exit(1);
|
|
5947
6366
|
}
|
|
5948
6367
|
const symbol = findSymbol(sourceFile, oldName);
|
|
5949
6368
|
if (!symbol) {
|
|
5950
|
-
console.log(
|
|
6369
|
+
console.log(chalk70.red(`Symbol "${oldName}" not found in ${file}`));
|
|
5951
6370
|
process.exit(1);
|
|
5952
6371
|
}
|
|
5953
6372
|
const grouped = groupReferences(symbol, cwd);
|
|
5954
6373
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
5955
6374
|
console.log(
|
|
5956
|
-
|
|
6375
|
+
chalk70.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
5957
6376
|
`)
|
|
5958
6377
|
);
|
|
5959
6378
|
for (const [refFile, lines] of grouped) {
|
|
5960
6379
|
console.log(
|
|
5961
|
-
` ${
|
|
6380
|
+
` ${chalk70.dim(refFile)}: lines ${chalk70.cyan(lines.join(", "))}`
|
|
5962
6381
|
);
|
|
5963
6382
|
}
|
|
5964
6383
|
if (options2.apply) {
|
|
5965
6384
|
symbol.rename(newName);
|
|
5966
6385
|
await project.save();
|
|
5967
|
-
console.log(
|
|
6386
|
+
console.log(chalk70.green(`
|
|
5968
6387
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
5969
6388
|
} else {
|
|
5970
|
-
console.log(
|
|
6389
|
+
console.log(chalk70.dim("\nDry run. Use --apply to execute."));
|
|
5971
6390
|
}
|
|
5972
6391
|
}
|
|
5973
6392
|
|
|
5974
6393
|
// src/commands/refactor/restructure/index.ts
|
|
5975
6394
|
import path37 from "path";
|
|
5976
|
-
import
|
|
6395
|
+
import chalk73 from "chalk";
|
|
5977
6396
|
|
|
5978
6397
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
5979
6398
|
import path29 from "path";
|
|
@@ -6216,50 +6635,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
6216
6635
|
|
|
6217
6636
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
6218
6637
|
import path33 from "path";
|
|
6219
|
-
import
|
|
6638
|
+
import chalk71 from "chalk";
|
|
6220
6639
|
function relPath(filePath) {
|
|
6221
6640
|
return path33.relative(process.cwd(), filePath);
|
|
6222
6641
|
}
|
|
6223
6642
|
function displayMoves(plan) {
|
|
6224
6643
|
if (plan.moves.length === 0) return;
|
|
6225
|
-
console.log(
|
|
6644
|
+
console.log(chalk71.bold("\nFile moves:"));
|
|
6226
6645
|
for (const move of plan.moves) {
|
|
6227
6646
|
console.log(
|
|
6228
|
-
` ${
|
|
6647
|
+
` ${chalk71.red(relPath(move.from))} \u2192 ${chalk71.green(relPath(move.to))}`
|
|
6229
6648
|
);
|
|
6230
|
-
console.log(
|
|
6649
|
+
console.log(chalk71.dim(` ${move.reason}`));
|
|
6231
6650
|
}
|
|
6232
6651
|
}
|
|
6233
6652
|
function displayRewrites(rewrites) {
|
|
6234
6653
|
if (rewrites.length === 0) return;
|
|
6235
6654
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
6236
|
-
console.log(
|
|
6655
|
+
console.log(chalk71.bold(`
|
|
6237
6656
|
Import rewrites (${affectedFiles.size} files):`));
|
|
6238
6657
|
for (const file of affectedFiles) {
|
|
6239
|
-
console.log(` ${
|
|
6658
|
+
console.log(` ${chalk71.cyan(relPath(file))}:`);
|
|
6240
6659
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
6241
6660
|
(r) => r.file === file
|
|
6242
6661
|
)) {
|
|
6243
6662
|
console.log(
|
|
6244
|
-
` ${
|
|
6663
|
+
` ${chalk71.red(`"${oldSpecifier}"`)} \u2192 ${chalk71.green(`"${newSpecifier}"`)}`
|
|
6245
6664
|
);
|
|
6246
6665
|
}
|
|
6247
6666
|
}
|
|
6248
6667
|
}
|
|
6249
6668
|
function displayPlan(plan) {
|
|
6250
6669
|
if (plan.warnings.length > 0) {
|
|
6251
|
-
console.log(
|
|
6252
|
-
for (const w of plan.warnings) console.log(
|
|
6670
|
+
console.log(chalk71.yellow("\nWarnings:"));
|
|
6671
|
+
for (const w of plan.warnings) console.log(chalk71.yellow(` ${w}`));
|
|
6253
6672
|
}
|
|
6254
6673
|
if (plan.newDirectories.length > 0) {
|
|
6255
|
-
console.log(
|
|
6674
|
+
console.log(chalk71.bold("\nNew directories:"));
|
|
6256
6675
|
for (const dir of plan.newDirectories)
|
|
6257
|
-
console.log(
|
|
6676
|
+
console.log(chalk71.green(` ${dir}/`));
|
|
6258
6677
|
}
|
|
6259
6678
|
displayMoves(plan);
|
|
6260
6679
|
displayRewrites(plan.rewrites);
|
|
6261
6680
|
console.log(
|
|
6262
|
-
|
|
6681
|
+
chalk71.dim(
|
|
6263
6682
|
`
|
|
6264
6683
|
Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
|
|
6265
6684
|
)
|
|
@@ -6269,18 +6688,18 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
|
|
|
6269
6688
|
// src/commands/refactor/restructure/executePlan.ts
|
|
6270
6689
|
import fs19 from "fs";
|
|
6271
6690
|
import path34 from "path";
|
|
6272
|
-
import
|
|
6691
|
+
import chalk72 from "chalk";
|
|
6273
6692
|
function executePlan(plan) {
|
|
6274
6693
|
const updatedContents = applyRewrites(plan.rewrites);
|
|
6275
6694
|
for (const [file, content] of updatedContents) {
|
|
6276
6695
|
fs19.writeFileSync(file, content, "utf-8");
|
|
6277
6696
|
console.log(
|
|
6278
|
-
|
|
6697
|
+
chalk72.cyan(` Rewrote imports in ${path34.relative(process.cwd(), file)}`)
|
|
6279
6698
|
);
|
|
6280
6699
|
}
|
|
6281
6700
|
for (const dir of plan.newDirectories) {
|
|
6282
6701
|
fs19.mkdirSync(dir, { recursive: true });
|
|
6283
|
-
console.log(
|
|
6702
|
+
console.log(chalk72.green(` Created ${path34.relative(process.cwd(), dir)}/`));
|
|
6284
6703
|
}
|
|
6285
6704
|
for (const move of plan.moves) {
|
|
6286
6705
|
const targetDir = path34.dirname(move.to);
|
|
@@ -6289,7 +6708,7 @@ function executePlan(plan) {
|
|
|
6289
6708
|
}
|
|
6290
6709
|
fs19.renameSync(move.from, move.to);
|
|
6291
6710
|
console.log(
|
|
6292
|
-
|
|
6711
|
+
chalk72.white(
|
|
6293
6712
|
` Moved ${path34.relative(process.cwd(), move.from)} \u2192 ${path34.relative(process.cwd(), move.to)}`
|
|
6294
6713
|
)
|
|
6295
6714
|
);
|
|
@@ -6304,7 +6723,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
6304
6723
|
if (entries.length === 0) {
|
|
6305
6724
|
fs19.rmdirSync(dir);
|
|
6306
6725
|
console.log(
|
|
6307
|
-
|
|
6726
|
+
chalk72.dim(
|
|
6308
6727
|
` Removed empty directory ${path34.relative(process.cwd(), dir)}`
|
|
6309
6728
|
)
|
|
6310
6729
|
);
|
|
@@ -6437,22 +6856,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
6437
6856
|
const targetPattern = pattern2 ?? "src";
|
|
6438
6857
|
const files = findSourceFiles2(targetPattern);
|
|
6439
6858
|
if (files.length === 0) {
|
|
6440
|
-
console.log(
|
|
6859
|
+
console.log(chalk73.yellow("No files found matching pattern"));
|
|
6441
6860
|
return;
|
|
6442
6861
|
}
|
|
6443
6862
|
const tsConfigPath = path37.resolve("tsconfig.json");
|
|
6444
6863
|
const plan = buildPlan(files, tsConfigPath);
|
|
6445
6864
|
if (plan.moves.length === 0) {
|
|
6446
|
-
console.log(
|
|
6865
|
+
console.log(chalk73.green("No restructuring needed"));
|
|
6447
6866
|
return;
|
|
6448
6867
|
}
|
|
6449
6868
|
displayPlan(plan);
|
|
6450
6869
|
if (options2.apply) {
|
|
6451
|
-
console.log(
|
|
6870
|
+
console.log(chalk73.bold("\nApplying changes..."));
|
|
6452
6871
|
executePlan(plan);
|
|
6453
|
-
console.log(
|
|
6872
|
+
console.log(chalk73.green("\nRestructuring complete"));
|
|
6454
6873
|
} else {
|
|
6455
|
-
console.log(
|
|
6874
|
+
console.log(chalk73.dim("\nDry run. Use --apply to execute."));
|
|
6456
6875
|
}
|
|
6457
6876
|
}
|
|
6458
6877
|
|
|
@@ -7000,14 +7419,14 @@ import {
|
|
|
7000
7419
|
import { dirname as dirname18, join as join26 } from "path";
|
|
7001
7420
|
|
|
7002
7421
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
7003
|
-
import
|
|
7422
|
+
import chalk74 from "chalk";
|
|
7004
7423
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
7005
7424
|
function validateStagedContent(filename, content) {
|
|
7006
7425
|
const firstLine = content.split("\n")[0];
|
|
7007
7426
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
7008
7427
|
if (!match) {
|
|
7009
7428
|
console.error(
|
|
7010
|
-
|
|
7429
|
+
chalk74.red(
|
|
7011
7430
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
7012
7431
|
)
|
|
7013
7432
|
);
|
|
@@ -7016,7 +7435,7 @@ function validateStagedContent(filename, content) {
|
|
|
7016
7435
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
7017
7436
|
if (!contentAfterLink) {
|
|
7018
7437
|
console.error(
|
|
7019
|
-
|
|
7438
|
+
chalk74.red(
|
|
7020
7439
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
7021
7440
|
)
|
|
7022
7441
|
);
|
|
@@ -7216,7 +7635,7 @@ import { mkdirSync as mkdirSync10 } from "fs";
|
|
|
7216
7635
|
import { join as join31 } from "path";
|
|
7217
7636
|
|
|
7218
7637
|
// src/commands/voice/checkLockFile.ts
|
|
7219
|
-
import { execSync as
|
|
7638
|
+
import { execSync as execSync32 } from "child_process";
|
|
7220
7639
|
import { existsSync as existsSync31, mkdirSync as mkdirSync9, readFileSync as readFileSync25, writeFileSync as writeFileSync23 } from "fs";
|
|
7221
7640
|
import { join as join30 } from "path";
|
|
7222
7641
|
function isProcessAlive(pid) {
|
|
@@ -7245,7 +7664,7 @@ function bootstrapVenv() {
|
|
|
7245
7664
|
if (existsSync31(getVenvPython())) return;
|
|
7246
7665
|
console.log("Setting up Python environment...");
|
|
7247
7666
|
const pythonDir = getPythonDir();
|
|
7248
|
-
|
|
7667
|
+
execSync32(
|
|
7249
7668
|
`uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
|
|
7250
7669
|
{
|
|
7251
7670
|
stdio: "inherit",
|
|
@@ -7409,14 +7828,14 @@ function registerVoice(program2) {
|
|
|
7409
7828
|
|
|
7410
7829
|
// src/commands/roam/auth.ts
|
|
7411
7830
|
import { randomBytes } from "crypto";
|
|
7412
|
-
import
|
|
7831
|
+
import chalk75 from "chalk";
|
|
7413
7832
|
|
|
7414
7833
|
// src/lib/openBrowser.ts
|
|
7415
|
-
import { execSync as
|
|
7834
|
+
import { execSync as execSync33 } from "child_process";
|
|
7416
7835
|
function tryExec(commands) {
|
|
7417
7836
|
for (const cmd of commands) {
|
|
7418
7837
|
try {
|
|
7419
|
-
|
|
7838
|
+
execSync33(cmd);
|
|
7420
7839
|
return true;
|
|
7421
7840
|
} catch {
|
|
7422
7841
|
}
|
|
@@ -7584,13 +8003,13 @@ async function auth() {
|
|
|
7584
8003
|
saveGlobalConfig(config);
|
|
7585
8004
|
const state = randomBytes(16).toString("hex");
|
|
7586
8005
|
console.log(
|
|
7587
|
-
|
|
8006
|
+
chalk75.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
7588
8007
|
);
|
|
7589
|
-
console.log(
|
|
7590
|
-
console.log(
|
|
7591
|
-
console.log(
|
|
8008
|
+
console.log(chalk75.white("http://localhost:14523/callback\n"));
|
|
8009
|
+
console.log(chalk75.blue("Opening browser for authorization..."));
|
|
8010
|
+
console.log(chalk75.dim("Waiting for authorization callback..."));
|
|
7592
8011
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
7593
|
-
console.log(
|
|
8012
|
+
console.log(chalk75.dim("Exchanging code for tokens..."));
|
|
7594
8013
|
const tokens = await exchangeToken({
|
|
7595
8014
|
code,
|
|
7596
8015
|
clientId,
|
|
@@ -7606,7 +8025,7 @@ async function auth() {
|
|
|
7606
8025
|
};
|
|
7607
8026
|
saveGlobalConfig(config);
|
|
7608
8027
|
console.log(
|
|
7609
|
-
|
|
8028
|
+
chalk75.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
7610
8029
|
);
|
|
7611
8030
|
}
|
|
7612
8031
|
|
|
@@ -7794,14 +8213,14 @@ function run2(name, args) {
|
|
|
7794
8213
|
}
|
|
7795
8214
|
|
|
7796
8215
|
// src/commands/statusLine.ts
|
|
7797
|
-
import
|
|
8216
|
+
import chalk76 from "chalk";
|
|
7798
8217
|
function formatNumber(num) {
|
|
7799
8218
|
return num.toLocaleString("en-US");
|
|
7800
8219
|
}
|
|
7801
8220
|
function colorizePercent(pct) {
|
|
7802
8221
|
const label2 = `${pct}%`;
|
|
7803
|
-
if (pct > 80) return
|
|
7804
|
-
if (pct > 40) return
|
|
8222
|
+
if (pct > 80) return chalk76.red(label2);
|
|
8223
|
+
if (pct > 40) return chalk76.yellow(label2);
|
|
7805
8224
|
return label2;
|
|
7806
8225
|
}
|
|
7807
8226
|
async function statusLine() {
|
|
@@ -7827,7 +8246,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
7827
8246
|
// src/commands/sync/syncClaudeMd.ts
|
|
7828
8247
|
import * as fs22 from "fs";
|
|
7829
8248
|
import * as path38 from "path";
|
|
7830
|
-
import
|
|
8249
|
+
import chalk77 from "chalk";
|
|
7831
8250
|
async function syncClaudeMd(claudeDir, targetBase) {
|
|
7832
8251
|
const source = path38.join(claudeDir, "CLAUDE.md");
|
|
7833
8252
|
const target = path38.join(targetBase, "CLAUDE.md");
|
|
@@ -7836,12 +8255,12 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
7836
8255
|
const targetContent = fs22.readFileSync(target, "utf-8");
|
|
7837
8256
|
if (sourceContent !== targetContent) {
|
|
7838
8257
|
console.log(
|
|
7839
|
-
|
|
8258
|
+
chalk77.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
7840
8259
|
);
|
|
7841
8260
|
console.log();
|
|
7842
8261
|
printDiff(targetContent, sourceContent);
|
|
7843
8262
|
const confirm = await promptConfirm(
|
|
7844
|
-
|
|
8263
|
+
chalk77.red("Overwrite existing CLAUDE.md?"),
|
|
7845
8264
|
false
|
|
7846
8265
|
);
|
|
7847
8266
|
if (!confirm) {
|
|
@@ -7857,7 +8276,7 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
7857
8276
|
// src/commands/sync/syncSettings.ts
|
|
7858
8277
|
import * as fs23 from "fs";
|
|
7859
8278
|
import * as path39 from "path";
|
|
7860
|
-
import
|
|
8279
|
+
import chalk78 from "chalk";
|
|
7861
8280
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
7862
8281
|
const source = path39.join(claudeDir, "settings.json");
|
|
7863
8282
|
const target = path39.join(targetBase, "settings.json");
|
|
@@ -7873,14 +8292,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
7873
8292
|
if (mergedContent !== normalizedTarget) {
|
|
7874
8293
|
if (!options2?.yes) {
|
|
7875
8294
|
console.log(
|
|
7876
|
-
|
|
8295
|
+
chalk78.yellow(
|
|
7877
8296
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
7878
8297
|
)
|
|
7879
8298
|
);
|
|
7880
8299
|
console.log();
|
|
7881
8300
|
printDiff(targetContent, mergedContent);
|
|
7882
8301
|
const confirm = await promptConfirm(
|
|
7883
|
-
|
|
8302
|
+
chalk78.red("Overwrite existing settings.json?"),
|
|
7884
8303
|
false
|
|
7885
8304
|
);
|
|
7886
8305
|
if (!confirm) {
|
|
@@ -7917,7 +8336,7 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
7917
8336
|
}
|
|
7918
8337
|
|
|
7919
8338
|
// src/commands/update.ts
|
|
7920
|
-
import { execSync as
|
|
8339
|
+
import { execSync as execSync34 } from "child_process";
|
|
7921
8340
|
import * as path41 from "path";
|
|
7922
8341
|
function isGlobalNpmInstall(dir) {
|
|
7923
8342
|
try {
|
|
@@ -7925,7 +8344,7 @@ function isGlobalNpmInstall(dir) {
|
|
|
7925
8344
|
if (resolved.split(path41.sep).includes("node_modules")) {
|
|
7926
8345
|
return true;
|
|
7927
8346
|
}
|
|
7928
|
-
const globalPrefix =
|
|
8347
|
+
const globalPrefix = execSync34("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
7929
8348
|
return resolved.toLowerCase().startsWith(path41.resolve(globalPrefix).toLowerCase());
|
|
7930
8349
|
} catch {
|
|
7931
8350
|
return false;
|
|
@@ -7936,18 +8355,18 @@ async function update() {
|
|
|
7936
8355
|
console.log(`Assist is installed at: ${installDir}`);
|
|
7937
8356
|
if (isGitRepo(installDir)) {
|
|
7938
8357
|
console.log("Detected git repo installation, pulling latest...");
|
|
7939
|
-
|
|
8358
|
+
execSync34("git pull", { cwd: installDir, stdio: "inherit" });
|
|
7940
8359
|
console.log("Installing dependencies...");
|
|
7941
|
-
|
|
8360
|
+
execSync34("npm i", { cwd: installDir, stdio: "inherit" });
|
|
7942
8361
|
console.log("Building...");
|
|
7943
|
-
|
|
8362
|
+
execSync34("npm run build", { cwd: installDir, stdio: "inherit" });
|
|
7944
8363
|
console.log("Syncing commands...");
|
|
7945
|
-
|
|
8364
|
+
execSync34("assist sync", { stdio: "inherit" });
|
|
7946
8365
|
} else if (isGlobalNpmInstall(installDir)) {
|
|
7947
8366
|
console.log("Detected global npm installation, updating...");
|
|
7948
|
-
|
|
8367
|
+
execSync34("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
|
|
7949
8368
|
console.log("Syncing commands...");
|
|
7950
|
-
|
|
8369
|
+
execSync34("assist sync", { stdio: "inherit" });
|
|
7951
8370
|
} else {
|
|
7952
8371
|
console.error(
|
|
7953
8372
|
"Could not determine installation method. Expected a git repo or global npm install."
|
|
@@ -7996,6 +8415,7 @@ registerDeploy(program);
|
|
|
7996
8415
|
registerComplexity(program);
|
|
7997
8416
|
registerNetframework(program);
|
|
7998
8417
|
registerNews(program);
|
|
8418
|
+
registerRavendb(program);
|
|
7999
8419
|
registerTranscript(program);
|
|
8000
8420
|
registerVoice(program);
|
|
8001
8421
|
program.parse();
|