@creativeintelligence/abbie 0.1.2 → 0.1.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.
- package/extensions/abbie/index.ts +64 -22
- package/oclif.manifest.json +1 -1
- package/package.json +5 -3
|
@@ -553,51 +553,93 @@ export default function abbieExtension(pi: ExtensionAPI) {
|
|
|
553
553
|
} catch { return []; }
|
|
554
554
|
}
|
|
555
555
|
|
|
556
|
-
// On session start: check if any providers are connected
|
|
556
|
+
// On session start: check if any providers are connected, try syncing from Convex
|
|
557
557
|
pi.on("session_start", async (_event, ctx) => {
|
|
558
|
-
const
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
);
|
|
558
|
+
const localProviders = await getConnectedProviders();
|
|
559
|
+
|
|
560
|
+
// If no local providers, try to pull credentials from Convex (for fresh installs)
|
|
561
|
+
if (localProviders.length === 0) {
|
|
562
|
+
await syncProvidersFromConvex();
|
|
563
|
+
const afterSync = await getConnectedProviders();
|
|
564
|
+
if (afterSync.length === 0 && ctx.hasUI) {
|
|
565
|
+
ctx.ui.notify(
|
|
566
|
+
"No AI provider connected. Connect one at Settings → Providers in the web app, or use /login here.",
|
|
567
|
+
"warning",
|
|
568
|
+
);
|
|
569
|
+
}
|
|
564
570
|
}
|
|
565
571
|
});
|
|
566
572
|
|
|
567
|
-
// Sync provider
|
|
568
|
-
pi.on("agent_end", async (_event,
|
|
569
|
-
// After first agent interaction, sync provider info to Convex
|
|
570
|
-
// This runs once per session via a simple flag
|
|
573
|
+
// Sync provider credentials to Convex after first agent interaction
|
|
574
|
+
pi.on("agent_end", async (_event, _ctx) => {
|
|
571
575
|
if ((pi as any).__providersSynced) return;
|
|
572
576
|
(pi as any).__providersSynced = true;
|
|
573
577
|
|
|
574
578
|
const providers = await getConnectedProviders();
|
|
575
579
|
if (providers.length === 0) return;
|
|
576
580
|
|
|
577
|
-
//
|
|
581
|
+
// Also sync credentials to Convex for sandbox injection
|
|
578
582
|
try {
|
|
579
583
|
const { existsSync, readFileSync } = await import("node:fs");
|
|
580
584
|
const { join } = await import("node:path");
|
|
581
585
|
const { homedir } = await import("node:os");
|
|
586
|
+
const authPath = join(homedir(), ".pi", "agent", "auth.json");
|
|
582
587
|
const configPath = join(homedir(), ".abbie", "config.json");
|
|
583
|
-
if (!existsSync(configPath)) return;
|
|
588
|
+
if (!existsSync(configPath) || !existsSync(authPath)) return;
|
|
584
589
|
const config = JSON.parse(readFileSync(configPath, "utf8"));
|
|
585
590
|
const convexUrl = config.convexUrl || process.env.NEXT_PUBLIC_CONVEX_URL;
|
|
586
591
|
const bridgeSecret = config.bridgeSecret || process.env.ABBIE_BRIDGE_SECRET;
|
|
587
592
|
if (!convexUrl || !bridgeSecret) return;
|
|
588
593
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
594
|
+
const siteUrl = convexUrl.replace('.convex.cloud', '.convex.site');
|
|
595
|
+
const authData = JSON.parse(readFileSync(authPath, "utf8"));
|
|
596
|
+
|
|
597
|
+
// Sync each provider's credentials
|
|
598
|
+
for (const providerId of providers) {
|
|
599
|
+
const cred = authData[providerId];
|
|
600
|
+
if (!cred?.access || !cred?.refresh) continue;
|
|
601
|
+
|
|
602
|
+
await fetch(`${siteUrl}/bridge/providers/complete`, {
|
|
603
|
+
method: "POST",
|
|
604
|
+
headers: {
|
|
605
|
+
"Content-Type": "application/json",
|
|
606
|
+
"x-bridge-secret": bridgeSecret,
|
|
607
|
+
},
|
|
608
|
+
body: JSON.stringify({
|
|
609
|
+
// Use a synthetic request ID (the endpoint handles upserts)
|
|
610
|
+
requestId: null,
|
|
611
|
+
accessToken: cred.access,
|
|
612
|
+
refreshToken: cred.refresh,
|
|
613
|
+
expiresAt: cred.expires || Date.now() + 3600_000,
|
|
614
|
+
provider: providerId,
|
|
615
|
+
}),
|
|
616
|
+
}).catch(() => {}); // best-effort
|
|
617
|
+
}
|
|
598
618
|
} catch { /* non-fatal */ }
|
|
599
619
|
});
|
|
600
620
|
|
|
621
|
+
/**
|
|
622
|
+
* Pull provider credentials from Convex and write to local auth.json.
|
|
623
|
+
* Used on fresh installs where user connected via web but auth.json is empty.
|
|
624
|
+
*/
|
|
625
|
+
async function syncProvidersFromConvex(): Promise<void> {
|
|
626
|
+
try {
|
|
627
|
+
const { existsSync, readFileSync, writeFileSync, mkdirSync, chmodSync } = await import("node:fs");
|
|
628
|
+
const { join } = await import("node:path");
|
|
629
|
+
const { homedir } = await import("node:os");
|
|
630
|
+
|
|
631
|
+
const configPath = join(homedir(), ".abbie", "config.json");
|
|
632
|
+
if (!existsSync(configPath)) return;
|
|
633
|
+
const config = JSON.parse(readFileSync(configPath, "utf8"));
|
|
634
|
+
const convexUrl = config.convexUrl || process.env.NEXT_PUBLIC_CONVEX_URL;
|
|
635
|
+
const bridgeSecret = config.bridgeSecret || process.env.ABBIE_BRIDGE_SECRET;
|
|
636
|
+
if (!convexUrl || !bridgeSecret) return;
|
|
637
|
+
|
|
638
|
+
// TODO: Add a bridge endpoint that returns stored credentials
|
|
639
|
+
// For now, the bridge handles credential sync via the poll loop
|
|
640
|
+
} catch { /* non-fatal */ }
|
|
641
|
+
}
|
|
642
|
+
|
|
601
643
|
// ===========================================================================
|
|
602
644
|
// Auto-bridge: start bridge daemon on Pi startup
|
|
603
645
|
// ===========================================================================
|
package/oclif.manifest.json
CHANGED
|
@@ -11672,5 +11672,5 @@
|
|
|
11672
11672
|
"summary": "Watch workspace windows (tmux panes) and stream updates"
|
|
11673
11673
|
}
|
|
11674
11674
|
},
|
|
11675
|
-
"version": "0.1.
|
|
11675
|
+
"version": "0.1.4"
|
|
11676
11676
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@creativeintelligence/abbie",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Abbie — agent orchestration CLI",
|
|
@@ -86,11 +86,13 @@
|
|
|
86
86
|
"@oclif/core": "^4",
|
|
87
87
|
"@oclif/plugin-help": "^6",
|
|
88
88
|
"@oclif/plugin-not-found": "^3",
|
|
89
|
-
"@lnittman/convex-encryption": "^0.1.0",
|
|
90
|
-
"@lnittman/icons": "^0.3.0",
|
|
91
89
|
"convex": "^1.31.6",
|
|
92
90
|
"tar-fs": "^3"
|
|
93
91
|
},
|
|
92
|
+
"optionalDependencies": {
|
|
93
|
+
"@lnittman/convex-encryption": "^0.1.0",
|
|
94
|
+
"@lnittman/icons": "^0.3.0"
|
|
95
|
+
},
|
|
94
96
|
"devDependencies": {
|
|
95
97
|
"@lnittman/config": "^0.1.1",
|
|
96
98
|
"@types/bun": "^1",
|