mixdog 0.7.3 → 0.7.4

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mixdog",
3
- "version": "0.7.3",
3
+ "version": "0.7.4",
4
4
  "description": "Claude Code all-in-one agent plugin — autonomous agents, continuous memory, cost-aware sub-agents, and syntax-aware code editing.",
5
5
  "hooks": "./hooks/hooks.json",
6
6
  "mcpServers": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mixdog",
3
- "version": "0.7.3",
3
+ "version": "0.7.4",
4
4
  "description": "Claude Code all-in-one bridge plugin: role-based bridge workers, continuous memory, and syntax-aware code editing.",
5
5
  "author": "mixdog contributors <dev@tribgames.com>",
6
6
  "license": "MIT",
package/setup/wizard.mjs CHANGED
@@ -13,7 +13,6 @@ import {
13
13
  mergeAgentConfig,
14
14
  mergeMemoryConfig,
15
15
  mergeConfig,
16
- mergeWebhookEndpointConfig,
17
16
  } from './config-merge.mjs';
18
17
 
19
18
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -152,14 +151,6 @@ function readUserWorkflow(dataDir) {
152
151
  }
153
152
  }
154
153
 
155
- function readJsonFile(path) {
156
- try {
157
- return JSON.parse(readFileSync(path, 'utf8'));
158
- } catch {
159
- return {};
160
- }
161
- }
162
-
163
154
  function writeUserWorkflow(dataDir, data) {
164
155
  const path = join(dataDir, 'user-workflow.json');
165
156
  const roles = Array.isArray(data?.roles) ? data.roles.slice() : [];
@@ -276,10 +267,10 @@ async function stepAddressForm(io, { updateSection, readSection }) {
276
267
  io.say('• Saved memory.user (title/name).');
277
268
  }
278
269
 
279
- async function stepWebhookRegister(io, { dataDir }) {
280
- io.say('\n── Step 3/7: Webhook registration ──');
281
- io.say('Create a webhook endpoint (saved under webhooks/<name>/). Enter to skip.');
282
- const enableRaw = await io.ask('Create webhook endpoint? [y/N]: ');
270
+ export async function stepWebhookReceiver(io, { updateSection, readSection }) {
271
+ io.say('\n── Step 3/7: Inbound webhooks (ngrok receiver) ──');
272
+ io.say('Global webhook tunnel for inbound HTTP (channels.webhook). Per-endpoint registration is configured later in the UI.');
273
+ const enableRaw = await io.ask('Enable inbound webhooks? [y/N]: ');
283
274
  if (isSkippableAnswer(enableRaw)) {
284
275
  io.say('• Skipped webhook setup.');
285
276
  return;
@@ -289,27 +280,27 @@ async function stepWebhookRegister(io, { dataDir }) {
289
280
  io.say('• Skipped webhook setup.');
290
281
  return;
291
282
  }
292
- const nameRaw = await io.ask('Endpoint name: ');
293
- const name = sanitizeName(String(nameRaw).trim());
294
- if (!name) {
295
- io.say('• Invalid or missing endpoint name skipped webhook setup.');
296
- return;
283
+ const { hasStoredSecret, SECRET_ACCOUNTS } = await import('../src/shared/config.mjs');
284
+ const channels = readSection('channels') || {};
285
+ const curWebhook = channels.webhook && typeof channels.webhook === 'object' ? channels.webhook : {};
286
+ const curDomain = String(curWebhook.domain || curWebhook.ngrokDomain || '').trim();
287
+ const domainBase =
288
+ 'Domain (ngrok, e.g. your-name.ngrok-free.dev — get it at dashboard.ngrok.com/domains)';
289
+ const domainPrompt = curDomain
290
+ ? `${domainBase} (current: ${curDomain}, Enter=keep): `
291
+ : `${domainBase}: `;
292
+ const domainRaw = await io.ask(domainPrompt);
293
+ const webhook = { enabled: true };
294
+ if (!isSkippableAnswer(domainRaw)) {
295
+ webhook.domain = String(domainRaw).trim();
297
296
  }
298
- const secret = (await io.askSecret('Webhook secret (Enter=skip): ')).trim();
299
- const channel = (await io.ask('Discord channel id (Enter=skip): ')).trim();
300
- const model = (await io.ask('Agent preset id (Enter=skip): ')).trim();
301
- const instructions = (await io.ask('Instructions (Enter=skip): ')).trim();
302
- const dir = join(dataDir, 'webhooks', name);
303
- mkdirSync(dir, { recursive: true });
304
- const configPath = join(dir, 'config.json');
305
- const incoming = {};
306
- if (secret) incoming.secret = secret;
307
- if (channel) incoming.channel = channel;
308
- if (model) incoming.model = model;
309
- const merged = mergeWebhookEndpointConfig(readJsonFile(configPath), incoming);
310
- writeFileSync(configPath, JSON.stringify(merged, null, 2) + '\n', 'utf8');
311
- writeFileSync(join(dir, 'instructions.md'), instructions, 'utf8');
312
- io.say(`• Webhook endpoint "${name}" saved (role: ${merged.role}).`);
297
+ const authPrompt = hasStoredSecret(SECRET_ACCOUNTS.webhookAuth)
298
+ ? 'Auth Token (stored, Enter=keep): '
299
+ : 'ngrok Auth Token [hidden]: ';
300
+ webhook.authtoken = (await io.askSecret(authPrompt)).trim();
301
+ const secrets = {};
302
+ updateSection('channels', (current) => mergeConfig(current, { webhook }, secrets));
303
+ io.say('• Inbound webhook receiver saved (channels.webhook enabled/domain; authtoken in keychain).');
313
304
  }
314
305
 
315
306
  async function stepProviderKeys(io, { updateSection }) {
@@ -412,7 +403,7 @@ export async function runSetupWizard(ioOverride = null) {
412
403
  await stepAddressForm(io, ctx);
413
404
  const discordSaved = await stepDiscordToken(io, ctx);
414
405
  await stepVoiceTranscription(io, ctx, discordSaved);
415
- await stepWebhookRegister(io, ctx);
406
+ await stepWebhookReceiver(io, ctx);
416
407
  await stepProviderKeys(io, ctx);
417
408
  await stepPresets(io, ctx);
418
409
  await stepRolePresetMapping(io, ctx);