@aglit-ai/cli 0.1.17084 → 0.1.17089

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 CHANGED
@@ -19,8 +19,10 @@ aglit uninstall
19
19
  Run `aglit` in an interactive terminal to open the guided setup. `aglit init`
20
20
  also runs this flow and installs the signed runtime if it is missing. Setup asks
21
21
  for a computer name and AI provider, then enables Anywhere Access. It runs in
22
- the background without a window-mode prompt. After setup, `aglit ui`
23
- opens the Desktop window using the same app and profile. `aglit start` hides its window without disabling its connection.
22
+ the background during setup, then opens the Desktop window when setup succeeds.
23
+ `aglit start` and `aglit ui` open the window using the same app and profile.
24
+ Use `aglit init --headless` or `aglit start --headless` to keep the window hidden
25
+ without disabling its connection. `aglit --help` (or `aglit -h`) lists commands.
24
26
 
25
27
  Setup opens Aglit's Google login in the browser,
26
28
  detects existing Codex/Claude logins, and uses a configured authenticated provider
@@ -139,11 +141,16 @@ separate from browser-control connectivity.
139
141
  This release supports Apple Silicon Macs. Windows publication is deferred until its signed native runtime is available.
140
142
 
141
143
  On macOS, interactive `aglit init` also checks for the BlackHole 2ch audio cable
142
- and installs the official Homebrew cask when it is missing. You can run
143
- `aglit audio status --json` or retry with `aglit audio setup`. Administrator
144
+ and installs the official Homebrew cask when it is missing. Rerun `aglit init` to resume setup. Administrator
144
145
  approval happens in your terminal. Unattended setup reports the required action
145
146
  without waiting for a password. Audio setup preserves existing BlackHole variants,
146
147
  default audio devices and active CoreAudio sessions; restart macOS when the
147
148
  installer requires it. In the remote app, select BlackHole 2ch as the microphone
148
149
  for forwarded microphone audio. Browser speaker playback still requires a click
149
150
  when autoplay is blocked.
151
+
152
+ When settings already exist, interactive `aglit init` shows the saved computer name,
153
+ account and provider and offers to reuse them. Choosing reuse preserves the saved
154
+ model connection without repeating discovery or selection. Explicit `--name` and
155
+ `--provider` options override the corresponding saved values. Unattended init reuses
156
+ saved settings by default. Permission and connection checks still run.
package/bin/aglit.cjs CHANGED
@@ -32,7 +32,6 @@ const help = `Aglit Computer Use
32
32
  aglit team --name "Team name" [--team TEAM_ID] [--workspace WORKSPACE_ID]
33
33
  aglit pipelines [--open]
34
34
  aglit providers
35
- aglit audio status | setup [--json]
36
35
  aglit models list | choose
37
36
  aglit models login copilot [--reauth] [--json]
38
37
  aglit models login-status copilot --attempt ATTEMPT_ID [--json]
@@ -79,11 +78,11 @@ async function main() {
79
78
  const [command = 'init', email, connectionId] = positionals;
80
79
  const options = {
81
80
  models: ['device','fingerprint','name','json','challenge','code','connection','connections','model','harness','attempt','reauth'],
82
- audio: ['json'], install: ['json', 'channel'], init: ['name', 'provider', 'account', 'json', 'channel'],
81
+ install: ['json', 'channel'], init: ['name', 'provider', 'account', 'json', 'channel'],
83
82
  start: ['json', 'channel'], ui: ['json'], status: ['json'], update: ['check', 'channel', 'json'], updates: ['json'], enable: [], disable: [], rename: ['name', 'json'], console: ['json'], teams: ['json', 'open'], team: ['name', 'team', 'workspace', 'json'], pipelines: ['open', 'json'], providers: ['json'], invite: ['team'], uninstall: [],
84
83
  };
85
- if (!Object.hasOwn(options, command) || Object.keys(values).some(key => !options[command].includes(key)) || positionals.length > (command === 'models' ? 3 : ['invite', 'updates', 'audio'].includes(command) ? 2 : 1)) throw Error('Invalid command or options. Run aglit --help.');
86
- if (installation.development && !['models','audio','status','init','providers','enable','disable','ui','start'].includes(command)) throw Error('Source profile supports model/setup, access and window commands; installed runtime management is separate');
84
+ if (!Object.hasOwn(options, command) || Object.keys(values).some(key => !options[command].includes(key)) || positionals.length > (command === 'models' ? 3 : ['invite', 'updates'].includes(command) ? 2 : 1)) throw Error('Invalid command or options. Run aglit --help.');
85
+ if (installation.development && !['models','status','init','providers','enable','disable','ui','start'].includes(command)) throw Error('Source profile supports model/setup, access and window commands; installed runtime management is separate');
87
86
  if (command === 'updates' && !['on', 'off', 'status'].includes(email)) throw Error('Use aglit updates on|off|status');
88
87
  if (values.channel !== undefined && !['latest', 'canary', 'embedded'].includes(values.channel)) throw Error('Update channel must be latest, canary or embedded');
89
88
  if (values.team && !/^[A-Za-z0-9._:-]{1,128}$/.test(values.team)) throw Error('Invalid team ID');
@@ -97,12 +96,6 @@ async function main() {
97
96
  if (values.name !== undefined && (!values.name.trim() || values.name.length > 100 || /[\x00-\x1f\x7f-\x9f]/.test(values.name))) throw Error('Computer name must contain 1–100 printable characters');
98
97
  const ui = await createUi(interactive);
99
98
  const installed = () => fs.existsSync(path.join(installation.root, 'installation.json'));
100
- if (command === 'audio') {
101
- if (!['status', 'setup'].includes(email)) throw Error('Use aglit audio status|setup');
102
- const audio = require('../src/mac-audio.cjs');
103
- ui.result(email === 'setup' ? audio.setup({ interactive }) : audio.status());
104
- ui.finish('Mac audio'); return;
105
- }
106
99
  if (command === 'update') {
107
100
  ui.result(await ui.step(values.check ? 'Check npm updates' : 'Update Aglit from npm', () => updates.update({check: Boolean(values.check), channel: values.channel})));
108
101
  ui.finish('Update check complete'); return;
@@ -226,16 +219,18 @@ async function main() {
226
219
  }
227
220
  if (values.account && state.email?.toLowerCase() !== values.account.toLowerCase())
228
221
  throw Error(`Signed in as ${state.email}; expected ${values.account}. Switch the browser sign-in account and rerun aglit init.`);
229
- if (interactive && !values.account && !await ui.confirmAccount(state.email))
222
+ const reuseSavedSetup = Boolean(state.name) && (!interactive || await ui.reuseSetup(state));
223
+ if (interactive && !reuseSavedSetup && !values.account && !await ui.confirmAccount(state.email))
230
224
  throw Object.assign(Error('Setup cancelled before enabling remote access.'), { cancelled: true });
231
225
  ui.info(`Signed in as ${state.email}`);
232
- if (!values.name && interactive) name = await ui.name(state.name || os.hostname());
226
+ if (!values.name && interactive && !reuseSavedSetup) name = await ui.name(state.name || os.hostname());
233
227
  name ||= state.name;
234
228
  if (!name) throw Error('Provide --name for unattended setup');
235
- const selected = await require('../src/model-connections.cjs').chooseModelConnection(control, { provider: values.provider, question: modelQuestion });
236
- for (const warning of selected.view.warnings || []) ui.info(warning);
229
+ const selected = reuseSavedSetup && !values.provider ? null :
230
+ await require('../src/model-connections.cjs').chooseModelConnection(control, { provider: values.provider, question: modelQuestion });
231
+ for (const warning of selected?.view.warnings || []) ui.info(warning);
237
232
  await ui.step('Save computer settings', () => control('configure', { name,
238
- ...(selected.connectionId ? { provider: 'aglit', model_connection_id: selected.connectionId } : values.provider && values.provider !== 'auto' ? { provider: values.provider } : {}) }));
233
+ ...(selected?.connectionId ? { provider: 'aglit', model_connection_id: selected.connectionId } : values.provider && values.provider !== 'auto' ? { provider: values.provider } : {}) }));
239
234
  if (process.platform === 'darwin') {
240
235
  try {
241
236
  const audio = require('../src/mac-audio.cjs').setup({ interactive });
@@ -243,7 +238,7 @@ async function main() {
243
238
  if (audio.restartRequired) ui.info('BlackHole is installed. Restart this Mac when convenient to enable the audio cable.');
244
239
  if (!interactive) ui.result({ audio });
245
240
  } catch (error) {
246
- ui.info(`${error.message} Run aglit audio setup to retry.`);
241
+ ui.info(`${error.message} Rerun aglit init to retry audio setup.`);
247
242
  }
248
243
  ui.permissions();
249
244
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aglit-ai/cli",
3
- "version": "0.1.17084",
3
+ "version": "0.1.17089",
4
4
  "description": "Install and manage Aglit Computer Use",
5
5
  "license": "UNLICENSED",
6
6
  "type": "commonjs",
package/src/ui.cjs CHANGED
@@ -43,6 +43,11 @@ async function createUi(interactive) {
43
43
  p.note((value.devices.length ? value.devices.map(device => `${clean(device.name)}${device.platform ? ' · ' + clean(device.platform) : ''}`).join('\n') + '\n\n' : 'No authorized pipeline devices.\n\n') +
44
44
  'https://pipelines.aglit.ai/\nOpen the encrypted viewer with aglit pipelines --open.', 'Pipeline devices');
45
45
  },
46
+ reuseSetup: state => {
47
+ p.note([`Computer ${clean(state.name)}`, `Account ${clean(state.email)}`,
48
+ state.provider && `Provider ${clean(state.provider)}`].filter(Boolean).join('\n'), 'Saved setup');
49
+ return answer(p.confirm({ message: 'Reuse these settings?', initialValue: true }));
50
+ },
46
51
  confirmAccount: email => answer(p.confirm({ message: `Register with ${clean(email)}?`, initialValue: true })),
47
52
  async step(label, action) {
48
53
  const spinner = p.spinner(); spinner.start(label);