jirallm 0.1.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.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +214 -0
  3. package/dist/cli/commands/auth.d.ts +7 -0
  4. package/dist/cli/commands/auth.d.ts.map +1 -0
  5. package/dist/cli/commands/auth.js +69 -0
  6. package/dist/cli/commands/auth.js.map +1 -0
  7. package/dist/cli/commands/doctor.d.ts +5 -0
  8. package/dist/cli/commands/doctor.d.ts.map +1 -0
  9. package/dist/cli/commands/doctor.js +191 -0
  10. package/dist/cli/commands/doctor.js.map +1 -0
  11. package/dist/cli/commands/init.d.ts +2 -0
  12. package/dist/cli/commands/init.d.ts.map +1 -0
  13. package/dist/cli/commands/init.js +198 -0
  14. package/dist/cli/commands/init.js.map +1 -0
  15. package/dist/cli/commands/orgs.d.ts +8 -0
  16. package/dist/cli/commands/orgs.d.ts.map +1 -0
  17. package/dist/cli/commands/orgs.js +81 -0
  18. package/dist/cli/commands/orgs.js.map +1 -0
  19. package/dist/cli/commands/profiles.d.ts +2 -0
  20. package/dist/cli/commands/profiles.d.ts.map +1 -0
  21. package/dist/cli/commands/profiles.js +20 -0
  22. package/dist/cli/commands/profiles.js.map +1 -0
  23. package/dist/cli/commands/setup.d.ts +7 -0
  24. package/dist/cli/commands/setup.d.ts.map +1 -0
  25. package/dist/cli/commands/setup.js +130 -0
  26. package/dist/cli/commands/setup.js.map +1 -0
  27. package/dist/cli/index.d.ts +3 -0
  28. package/dist/cli/index.d.ts.map +1 -0
  29. package/dist/cli/index.js +267 -0
  30. package/dist/cli/index.js.map +1 -0
  31. package/dist/cli/issueKey.d.ts +13 -0
  32. package/dist/cli/issueKey.d.ts.map +1 -0
  33. package/dist/cli/issueKey.js +50 -0
  34. package/dist/cli/issueKey.js.map +1 -0
  35. package/dist/cli/issueKey.test.d.ts +2 -0
  36. package/dist/cli/issueKey.test.d.ts.map +1 -0
  37. package/dist/cli/issueKey.test.js +48 -0
  38. package/dist/cli/issueKey.test.js.map +1 -0
  39. package/dist/index.d.ts +10 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +6 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/lib/config.d.ts +49 -0
  44. package/dist/lib/config.d.ts.map +1 -0
  45. package/dist/lib/config.js +173 -0
  46. package/dist/lib/config.js.map +1 -0
  47. package/dist/lib/config.test.d.ts +2 -0
  48. package/dist/lib/config.test.d.ts.map +1 -0
  49. package/dist/lib/config.test.js +130 -0
  50. package/dist/lib/config.test.js.map +1 -0
  51. package/dist/lib/configSchema.d.ts +42 -0
  52. package/dist/lib/configSchema.d.ts.map +1 -0
  53. package/dist/lib/configSchema.js +41 -0
  54. package/dist/lib/configSchema.js.map +1 -0
  55. package/dist/lib/credentials.d.ts +8 -0
  56. package/dist/lib/credentials.d.ts.map +1 -0
  57. package/dist/lib/credentials.js +62 -0
  58. package/dist/lib/credentials.js.map +1 -0
  59. package/dist/lib/credentials.test.d.ts +2 -0
  60. package/dist/lib/credentials.test.d.ts.map +1 -0
  61. package/dist/lib/credentials.test.js +35 -0
  62. package/dist/lib/credentials.test.js.map +1 -0
  63. package/dist/lib/exporter.d.ts +28 -0
  64. package/dist/lib/exporter.d.ts.map +1 -0
  65. package/dist/lib/exporter.js +149 -0
  66. package/dist/lib/exporter.js.map +1 -0
  67. package/dist/lib/jiraClient.d.ts +129 -0
  68. package/dist/lib/jiraClient.d.ts.map +1 -0
  69. package/dist/lib/jiraClient.js +308 -0
  70. package/dist/lib/jiraClient.js.map +1 -0
  71. package/dist/lib/platform.d.ts +9 -0
  72. package/dist/lib/platform.d.ts.map +1 -0
  73. package/dist/lib/platform.js +82 -0
  74. package/dist/lib/platform.js.map +1 -0
  75. package/dist/lib/runCommand.d.ts +7 -0
  76. package/dist/lib/runCommand.d.ts.map +1 -0
  77. package/dist/lib/runCommand.js +26 -0
  78. package/dist/lib/runCommand.js.map +1 -0
  79. package/dist/lib/videoFrameExtractor.d.ts +22 -0
  80. package/dist/lib/videoFrameExtractor.d.ts.map +1 -0
  81. package/dist/lib/videoFrameExtractor.js +234 -0
  82. package/dist/lib/videoFrameExtractor.js.map +1 -0
  83. package/package.json +57 -0
@@ -0,0 +1,198 @@
1
+ import { intro, outro, text, password, confirm, select, isCancel, cancel, note } from '@clack/prompts';
2
+ import { resolveConfigPath, readConfig, upsertOrg, upsertProject, } from '../../lib/config.js';
3
+ import { setToken } from '../../lib/credentials.js';
4
+ import { checkFFmpegInstalled } from '../../lib/videoFrameExtractor.js';
5
+ import { detectOS, hasHomebrew } from '../../lib/platform.js';
6
+ function exitIfCancelled(value) {
7
+ if (isCancel(value)) {
8
+ cancel('Cancelled.');
9
+ process.exit(0);
10
+ }
11
+ return value;
12
+ }
13
+ const ORG_NAME_RE = /^[a-zA-Z0-9_.-]+$/;
14
+ const PROJECT_KEY_RE = /^[A-Z][A-Z0-9_]*$/;
15
+ async function promptOrg(existingOrgNames) {
16
+ if (existingOrgNames.length === 0) {
17
+ const name = exitIfCancelled(await text({
18
+ message: 'Organization name (short identifier, e.g. "acme")\n\x1b[2mA short identifier used to group projects and select via `--org acme`.\x1b[22m',
19
+ placeholder: 'acme',
20
+ validate: (v) => {
21
+ if (!v)
22
+ return 'Required';
23
+ if (!ORG_NAME_RE.test(v))
24
+ return 'Use letters, digits, _, ., -';
25
+ },
26
+ }));
27
+ return { name, isNew: true };
28
+ }
29
+ const choice = exitIfCancelled(await select({
30
+ message: 'What do you want to do?\n\x1b[2mChoose to add a project to an existing org or set up a new one.\x1b[22m',
31
+ options: [
32
+ ...existingOrgNames.map((n) => ({ value: `existing:${n}`, label: `Add a project to "${n}"` })),
33
+ { value: '__new__', label: 'Create a new organization' },
34
+ ],
35
+ }));
36
+ if (choice.startsWith('existing:')) {
37
+ return { name: choice.slice('existing:'.length), isNew: false };
38
+ }
39
+ const name = exitIfCancelled(await text({
40
+ message: 'New organization name\n\x1b[2mA short identifier used to group projects and select via `--org acme`.\x1b[22m',
41
+ placeholder: 'acme',
42
+ validate: (v) => {
43
+ if (!v)
44
+ return 'Required';
45
+ if (!ORG_NAME_RE.test(v))
46
+ return 'Use letters, digits, _, ., -';
47
+ if (existingOrgNames.includes(v))
48
+ return 'Organization already exists';
49
+ },
50
+ }));
51
+ return { name, isNew: true };
52
+ }
53
+ async function promptOrgFields(name) {
54
+ const baseUrl = exitIfCancelled(await text({
55
+ message: 'Jira base URL\n\x1b[2mThe full URL of your Jira Cloud workspace, including https://.\x1b[22m',
56
+ placeholder: 'https://your-org.atlassian.net',
57
+ validate: (v) => {
58
+ if (!v)
59
+ return 'Required';
60
+ if (!/^https?:\/\//.test(v))
61
+ return 'Must start with http(s)://';
62
+ },
63
+ }));
64
+ const userEmail = exitIfCancelled(await text({
65
+ message: 'Jira account email\n\x1b[2mThe email you log into Jira with — used together with the API token for auth.\x1b[22m',
66
+ placeholder: 'you@example.com',
67
+ validate: (v) => (v && v.includes('@') ? undefined : 'Looks invalid'),
68
+ }));
69
+ const includeSubtasks = exitIfCancelled(await confirm({
70
+ message: 'Include subtasks by default?\n\x1b[2mIf enabled, exports also include child subtasks of each issue.\x1b[22m',
71
+ initialValue: false,
72
+ }));
73
+ const enableVideo = exitIfCancelled(await confirm({
74
+ message: "Extract video frames by default?\n\x1b[2mIf enabled, jirallm samples frames from attached videos so LLMs can 'see' them. Requires ffmpeg.\x1b[22m",
75
+ initialValue: true,
76
+ }));
77
+ let videoFrames;
78
+ if (enableVideo) {
79
+ const fps = exitIfCancelled(await text({
80
+ message: 'Frame extraction FPS\n\x1b[2mHow many frames per second to sample from each video.\x1b[22m',
81
+ defaultValue: '5',
82
+ placeholder: '5',
83
+ }));
84
+ const maxFrames = exitIfCancelled(await text({
85
+ message: 'Max frames kept per video\n\x1b[2mCap on frames kept per video — controls token cost.\x1b[22m',
86
+ defaultValue: '10',
87
+ placeholder: '10',
88
+ }));
89
+ videoFrames = {
90
+ enabled: true,
91
+ fps: parseInt(fps, 10) || 5,
92
+ maxFrames: parseInt(maxFrames, 10) || 10,
93
+ };
94
+ }
95
+ else {
96
+ videoFrames = { enabled: false };
97
+ }
98
+ const apiToken = exitIfCancelled(await password({
99
+ message: 'Jira API token\n\x1b[2mCreate one at https://id.atlassian.com/manage-profile/security/api-tokens. Stored in your OS keychain.\x1b[22m',
100
+ validate: (v) => (v ? undefined : 'Required'),
101
+ }));
102
+ const org = {
103
+ name,
104
+ baseUrl,
105
+ userEmail,
106
+ includeSubtasks: includeSubtasks || undefined,
107
+ videoFrames,
108
+ projects: {},
109
+ };
110
+ return { org, apiToken };
111
+ }
112
+ function parseProjectKeysInput(input, existingKeys) {
113
+ const keys = input
114
+ .split(',')
115
+ .map((k) => k.trim().toUpperCase())
116
+ .filter((k) => k.length > 0);
117
+ if (keys.length === 0)
118
+ return 'Required';
119
+ const seen = new Set();
120
+ for (const k of keys) {
121
+ if (!PROJECT_KEY_RE.test(k))
122
+ return `Invalid key "${k}". Use uppercase letters, digits, _ (must start with a letter).`;
123
+ if (seen.has(k))
124
+ return `Duplicate key "${k}" in input.`;
125
+ if (existingKeys.includes(k))
126
+ return `Project key "${k}" already exists in this org.`;
127
+ seen.add(k);
128
+ }
129
+ return keys;
130
+ }
131
+ async function promptProject(orgName, existingKeys) {
132
+ const raw = exitIfCancelled(await text({
133
+ message: `Project keys for "${orgName}" (uppercase, comma-separated, e.g. PROJ,CORE)\n\x1b[2mJira project key prefixes shown in issue IDs (e.g. PROJ in PROJ-123). Add several at once.\x1b[22m`,
134
+ placeholder: 'PROJ,CORE',
135
+ validate: (v) => {
136
+ const result = parseProjectKeysInput(v ?? '', existingKeys);
137
+ if (typeof result === 'string')
138
+ return result;
139
+ },
140
+ }));
141
+ const parsed = parseProjectKeysInput(raw, existingKeys);
142
+ if (typeof parsed === 'string')
143
+ throw new Error(parsed);
144
+ const outputDir = exitIfCancelled(await text({
145
+ message: 'Default output directory for these projects (optional)\n\x1b[2mWhere exports for these projects will be written. Leave empty to choose per-export with `--output-dir`.\x1b[22m',
146
+ placeholder: './jira-export',
147
+ }));
148
+ const dir = outputDir || undefined;
149
+ return parsed.map((key) => ({ key, outputDir: dir }));
150
+ }
151
+ export async function runInit() {
152
+ intro('jirallm init');
153
+ const existing = readConfig();
154
+ const existingOrgNames = Object.keys(existing.orgs ?? {});
155
+ const { name: orgName, isNew } = await promptOrg(existingOrgNames);
156
+ let newOrgVideoFrames;
157
+ if (isNew) {
158
+ const { org, apiToken } = await promptOrgFields(orgName);
159
+ newOrgVideoFrames = org.videoFrames;
160
+ upsertOrg(org);
161
+ try {
162
+ await setToken(orgName, apiToken);
163
+ }
164
+ catch (err) {
165
+ const msg = err instanceof Error ? err.message : String(err);
166
+ note(`Org saved. Token NOT stored in keychain: ${msg}\nFix the keychain (e.g. \`pnpm rebuild keytar\`) and rerun \`jirallm auth set --org ${orgName}\`.`, 'Partial success');
167
+ }
168
+ }
169
+ const orgRaw = readConfig().orgs?.[orgName];
170
+ const existingProjectKeys = Object.keys(orgRaw?.projects ?? {});
171
+ const projects = await promptProject(orgName, existingProjectKeys);
172
+ for (const p of projects)
173
+ upsertProject(orgName, p);
174
+ note(`Config saved to ${resolveConfigPath()}`, 'Done');
175
+ if (isNew && newOrgVideoFrames?.enabled) {
176
+ await maybeOfferSetup();
177
+ }
178
+ const sample = projects[0].key;
179
+ outro(`Use it with: jirallm ${sample}-123 (or jirallm ${orgName}/${sample}-123 to disambiguate)`);
180
+ }
181
+ async function maybeOfferSetup() {
182
+ if (await checkFFmpegInstalled())
183
+ return;
184
+ note('Video frames are enabled but ffmpeg was not found on your PATH.\n`jirallm setup` can install it for you.', 'ffmpeg missing');
185
+ // On macOS without Homebrew, setup may cascade into a long Homebrew + Xcode CLT install.
186
+ // Default the prompt to "no" there so users opt in deliberately.
187
+ const os = detectOS();
188
+ const defaultYes = os === 'macos' ? await hasHomebrew() : true;
189
+ const proceed = await confirm({
190
+ message: 'Run `jirallm setup` now?\n\x1b[2mYou can also run it manually later, or use `jirallm setup --bundled` for a self-contained install.\x1b[22m',
191
+ initialValue: defaultYes,
192
+ });
193
+ if (isCancel(proceed) || proceed !== true)
194
+ return;
195
+ const { runSetup } = await import('./setup.js');
196
+ await runSetup({});
197
+ }
198
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare function runOrgsList(): Promise<void>;
2
+ export declare function runOrgsRemove(orgName: string, opts?: {
3
+ yes?: boolean;
4
+ }): Promise<void>;
5
+ export declare function runProjectRemove(orgName: string, projectKey: string, opts?: {
6
+ yes?: boolean;
7
+ }): Promise<void>;
8
+ //# sourceMappingURL=orgs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orgs.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/orgs.ts"],"names":[],"mappings":"AAUA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CA2BjD;AAYD,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BhG;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3B,OAAO,CAAC,IAAI,CAAC,CAqBf"}
@@ -0,0 +1,81 @@
1
+ import { confirm, isCancel, cancel } from '@clack/prompts';
2
+ import { readConfig, resolveConfigPath, removeOrg, removeProject, listOrgs, } from '../../lib/config.js';
3
+ import { hasStoredToken, removeToken } from '../../lib/credentials.js';
4
+ export async function runOrgsList() {
5
+ const path = resolveConfigPath();
6
+ const raw = readConfig(path);
7
+ const orgs = raw.orgs ?? {};
8
+ const names = Object.keys(orgs);
9
+ if (names.length === 0) {
10
+ console.log(`No organizations configured.\nConfig path: ${path}\nRun \`jirallm init\` to create one.`);
11
+ return;
12
+ }
13
+ console.log(`Config: ${path}\n`);
14
+ for (const name of names) {
15
+ const tokenStatus = (await hasStoredToken(name)) ? 'token: stored' : 'token: missing';
16
+ const o = orgs[name];
17
+ console.log(` ${name} (${tokenStatus}) ${o.base_url ?? ''}`);
18
+ const projects = o.projects ?? {};
19
+ const projectKeys = Object.keys(projects);
20
+ if (projectKeys.length === 0) {
21
+ console.log(' (no projects)');
22
+ continue;
23
+ }
24
+ for (const key of projectKeys) {
25
+ const outputDir = projects[key].output_dir ? ` → ${projects[key].output_dir}` : '';
26
+ console.log(` ${key}${outputDir}`);
27
+ }
28
+ }
29
+ }
30
+ function ensureOrgExists(orgName) {
31
+ const orgs = listOrgs();
32
+ if (!orgs.includes(orgName)) {
33
+ console.error(`Organization "${orgName}" not found. Existing orgs: ${orgs.join(', ') || '(none)'}`);
34
+ process.exit(1);
35
+ }
36
+ }
37
+ export async function runOrgsRemove(orgName, opts = {}) {
38
+ ensureOrgExists(orgName);
39
+ if (!opts.yes) {
40
+ const ok = await confirm({
41
+ message: `Remove organization "${orgName}" and all its projects?\n\x1b[2mAlso removes the stored API token for this org from the keychain.\x1b[22m`,
42
+ initialValue: false,
43
+ });
44
+ if (isCancel(ok) || ok !== true) {
45
+ cancel('Cancelled.');
46
+ return;
47
+ }
48
+ }
49
+ const result = removeOrg(orgName);
50
+ if (!result.removed) {
51
+ console.log(`Organization "${orgName}" not found (nothing to remove).`);
52
+ return;
53
+ }
54
+ try {
55
+ await removeToken(orgName);
56
+ }
57
+ catch {
58
+ // best-effort; keychain may be unavailable
59
+ }
60
+ console.log(`Removed organization "${orgName}".`);
61
+ }
62
+ export async function runProjectRemove(orgName, projectKey, opts = {}) {
63
+ ensureOrgExists(orgName);
64
+ if (!opts.yes) {
65
+ const ok = await confirm({
66
+ message: `Remove project "${projectKey}" from org "${orgName}"?`,
67
+ initialValue: false,
68
+ });
69
+ if (isCancel(ok) || ok !== true) {
70
+ cancel('Cancelled.');
71
+ return;
72
+ }
73
+ }
74
+ const result = removeProject(orgName, projectKey);
75
+ if (!result.removed) {
76
+ console.log(`Project "${projectKey}" not found in org "${orgName}" (nothing to remove).`);
77
+ return;
78
+ }
79
+ console.log(`Removed project "${projectKey}" from "${orgName}".`);
80
+ }
81
+ //# sourceMappingURL=orgs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orgs.js","sourceRoot":"","sources":["../../../src/cli/commands/orgs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runProfilesList(): Promise<void>;
2
+ //# sourceMappingURL=profiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/profiles.ts"],"names":[],"mappings":"AAGA,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAkBrD"}
@@ -0,0 +1,20 @@
1
+ import { readConfig, resolveConfigPath } from '../../lib/config.js';
2
+ import { hasStoredToken } from '../../lib/credentials.js';
3
+ export async function runProfilesList() {
4
+ const path = resolveConfigPath();
5
+ const raw = readConfig(path);
6
+ const names = Object.keys(raw.profiles ?? {});
7
+ if (names.length === 0) {
8
+ console.log(`No profiles configured.\nConfig path: ${path}\nRun \`jirallm init\` to create one.`);
9
+ return;
10
+ }
11
+ console.log(`Config: ${path}\nDefault: ${raw.default_profile ?? '(none)'}\n`);
12
+ for (const name of names) {
13
+ const tokenStatus = (await hasStoredToken(name)) ? 'token: stored' : 'token: missing';
14
+ const marker = name === raw.default_profile ? '*' : ' ';
15
+ const p = raw.profiles[name];
16
+ const inherits = p.inherits ? ` inherits=${p.inherits}` : '';
17
+ console.log(` ${marker} ${name} (${tokenStatus})${inherits} ${p.base_url ?? ''}`);
18
+ }
19
+ }
20
+ //# sourceMappingURL=profiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../../src/cli/commands/profiles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAE9C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,yCAAyC,IAAI,uCAAuC,CAAC,CAAC;QAClG,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,cAAc,GAAG,CAAC,eAAe,IAAI,QAAQ,IAAI,CAAC,CAAC;IAC9E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,WAAW,GAAG,CAAC,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,gBAAgB,CAAC;QACtF,MAAM,MAAM,GAAG,IAAI,KAAK,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QACxD,MAAM,CAAC,GAAG,GAAG,CAAC,QAAS,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,IAAI,IAAI,MAAM,WAAW,IAAI,QAAQ,KAAK,CAAC,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC,CAAC;IACvF,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ type SetupOpts = {
2
+ bundled?: boolean;
3
+ yes?: boolean;
4
+ };
5
+ export declare function runSetup(opts?: SetupOpts): Promise<void>;
6
+ export {};
7
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/setup.ts"],"names":[],"mappings":"AAYA,KAAK,SAAS,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAmFtD,wBAAsB,QAAQ,CAAC,IAAI,GAAE,SAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAyDlE"}
@@ -0,0 +1,130 @@
1
+ import { spawn } from 'child_process';
2
+ import { intro, outro, confirm, note, isCancel, cancel } from '@clack/prompts';
3
+ import { checkFFmpegInstalled, resolveFfmpegBinary } from '../../lib/videoFrameExtractor.js';
4
+ import { detectOS, detectPackageManager, ffmpegInstallCommand, hasHomebrew, HOMEBREW_INSTALL_CMD, } from '../../lib/platform.js';
5
+ function runInteractive(command) {
6
+ return new Promise((resolve) => {
7
+ const child = spawn(command, { shell: true, stdio: 'inherit' });
8
+ child.on('exit', (code) => resolve(code ?? 1));
9
+ child.on('error', () => resolve(1));
10
+ });
11
+ }
12
+ async function confirmStep(message, defaultYes) {
13
+ const ok = await confirm({ message, initialValue: defaultYes });
14
+ if (isCancel(ok)) {
15
+ cancel('Cancelled.');
16
+ return false;
17
+ }
18
+ return ok === true;
19
+ }
20
+ function detectGlobalInstaller() {
21
+ const ua = process.env.npm_config_user_agent ?? '';
22
+ if (ua.includes('pnpm'))
23
+ return 'pnpm add -g ffmpeg-static';
24
+ if (ua.includes('yarn'))
25
+ return 'yarn global add ffmpeg-static';
26
+ // default: npm
27
+ return 'npm install -g ffmpeg-static';
28
+ }
29
+ async function installBundled(opts) {
30
+ const cmd = detectGlobalInstaller();
31
+ note(`Will run:\n ${cmd}`, 'Bundled ffmpeg-static install');
32
+ if (!opts.yes && !(await confirmStep('Proceed with installing ffmpeg-static globally?', true))) {
33
+ return 1;
34
+ }
35
+ const code = await runInteractive(cmd);
36
+ if (code !== 0) {
37
+ console.error(`\nInstall command exited with code ${code}.`);
38
+ return code;
39
+ }
40
+ const resolved = await resolveFfmpegBinary();
41
+ if (resolved) {
42
+ console.log(`\nffmpeg resolved at: ${resolved}`);
43
+ return 0;
44
+ }
45
+ console.error('\nffmpeg-static installed but jirallm could not resolve it. Verify the global install path is on NODE_PATH.');
46
+ return 1;
47
+ }
48
+ async function installViaPackageManager(pm, opts) {
49
+ const cmd = ffmpegInstallCommand(pm);
50
+ if (!cmd)
51
+ return 1;
52
+ note(`Will run:\n ${cmd}`, 'Installing ffmpeg');
53
+ if (!opts.yes && !(await confirmStep(`Run \`${cmd}\`?`, true))) {
54
+ return 1;
55
+ }
56
+ return runInteractive(cmd);
57
+ }
58
+ async function installHomebrew() {
59
+ const disclosure = [
60
+ 'Homebrew is not installed. The official installer:',
61
+ ' • Downloads and runs a script from raw.githubusercontent.com/Homebrew',
62
+ ' • Requires sudo (you will be prompted for your password)',
63
+ ' • May trigger Xcode Command Line Tools install (~1GB, GUI prompt)',
64
+ ' • Takes 5–15 minutes on a fresh machine',
65
+ '',
66
+ `Install command:\n ${HOMEBREW_INSTALL_CMD}`,
67
+ ].join('\n');
68
+ note(disclosure, 'Homebrew install — read carefully');
69
+ // Homebrew install ALWAYS requires interactive consent — never auto via --yes.
70
+ if (!(await confirmStep('Install Homebrew now?', false))) {
71
+ console.log('Skipped Homebrew install. See https://brew.sh for manual instructions.');
72
+ return 1;
73
+ }
74
+ const code = await runInteractive(HOMEBREW_INSTALL_CMD);
75
+ if (code !== 0) {
76
+ console.error(`\nHomebrew installer exited with code ${code}.`);
77
+ }
78
+ return code;
79
+ }
80
+ export async function runSetup(opts = {}) {
81
+ intro('jirallm setup');
82
+ if (opts.bundled) {
83
+ const code = await installBundled(opts);
84
+ if (code === 0)
85
+ outro('Bundled ffmpeg ready.');
86
+ else
87
+ process.exit(code);
88
+ return;
89
+ }
90
+ if (await checkFFmpegInstalled()) {
91
+ outro('ffmpeg already installed. Nothing to do.');
92
+ return;
93
+ }
94
+ const os = detectOS();
95
+ if (os === 'macos') {
96
+ if (!(await hasHomebrew())) {
97
+ const hbCode = await installHomebrew();
98
+ if (hbCode !== 0) {
99
+ note('You can also use the bundled fallback:\n jirallm setup --bundled', 'Alternative');
100
+ process.exit(hbCode);
101
+ }
102
+ }
103
+ const pm = await detectPackageManager();
104
+ const code = await installViaPackageManager(pm, opts);
105
+ if (code !== 0)
106
+ process.exit(code);
107
+ }
108
+ else if (os === 'linux') {
109
+ const pm = await detectPackageManager();
110
+ if (pm === 'none') {
111
+ note('No supported package manager detected (apt/dnf/pacman). Install ffmpeg manually or use:\n jirallm setup --bundled', 'Manual install required');
112
+ process.exit(1);
113
+ }
114
+ const code = await installViaPackageManager(pm, opts);
115
+ if (code !== 0)
116
+ process.exit(code);
117
+ }
118
+ else {
119
+ note('Automatic install not supported on this OS. Options:\n • Install ffmpeg manually (https://ffmpeg.org/download.html)\n • Use bundled fallback: jirallm setup --bundled', 'Manual install required');
120
+ process.exit(1);
121
+ }
122
+ // Re-verify
123
+ if (await checkFFmpegInstalled()) {
124
+ outro('ffmpeg installed successfully.');
125
+ return;
126
+ }
127
+ console.error('Install reported success but ffmpeg is still not on PATH. Open a new shell and try `ffmpeg -version`.');
128
+ process.exit(1);
129
+ }
130
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/cli/commands/setup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}