takomi 2.1.30 → 2.1.32
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/.pi/extensions/notify-sound/index.ts +262 -262
- package/.pi/extensions/oauth-router/README.md +2 -1
- package/.pi/extensions/oauth-router/index.ts +130 -41
- package/.pi/extensions/oauth-router/provider.ts +115 -3
- package/.pi/extensions/oauth-router/types.ts +18 -0
- package/.pi/extensions/takomi-context-manager/diagnostics-tools.ts +1 -1
- package/.pi/extensions/takomi-context-manager/index.ts +1 -1
- package/.pi/extensions/takomi-context-manager/model-policy-gate.ts +1 -1
- package/.pi/extensions/takomi-context-manager/policy-tools.ts +1 -1
- package/.pi/extensions/takomi-context-manager/prerequisite-gates.ts +1 -1
- package/.pi/extensions/takomi-context-manager/skill-tools.ts +1 -1
- package/.pi/extensions/takomi-runtime/commands.ts +1 -1
- package/.pi/extensions/takomi-runtime/context-panel.ts +708 -708
- package/.pi/extensions/takomi-runtime/index.ts +2 -2
- package/.pi/extensions/takomi-runtime/shared.ts +1 -1
- package/.pi/extensions/takomi-runtime/subagent-controller.ts +1 -1
- package/.pi/extensions/takomi-runtime/subagent-render.ts +1 -1
- package/.pi/extensions/takomi-runtime/subagent-types.ts +11 -11
- package/.pi/extensions/takomi-runtime/ui.ts +2 -2
- package/.pi/extensions/takomi-subagents/agents.ts +1 -1
- package/.pi/extensions/takomi-subagents/index.ts +1 -1
- package/.pi/extensions/takomi-subagents/native-render.ts +3 -3
- package/.pi/extensions/takomi-subagents/pi-subagents-engine.ts +2 -2
- package/.pi/extensions/takomi-subagents/tool-runner.ts +1 -1
- package/package.json +5 -9
- package/src/doctor.js +1 -1
- package/src/pi-harness.js +34 -11
- package/src/pi-optional-features.js +1 -6
|
@@ -1,41 +1,130 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { registerRouterCommands, formatStatusReport } from "./commands.ts";
|
|
3
|
-
import { registerRouterProvider, RouterRuntime } from "./provider.ts";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
1
|
+
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { registerRouterCommands, formatStatusReport } from "./commands.ts";
|
|
3
|
+
import { registerRouterProvider, RouterRuntime } from "./provider.ts";
|
|
4
|
+
import type { RouterUiEvent } from "./types.ts";
|
|
5
|
+
|
|
6
|
+
function getHealthSummary(runtime: RouterRuntime) {
|
|
7
|
+
const rows = runtime.getStatusRows();
|
|
8
|
+
const healthy = rows.filter((row) => {
|
|
9
|
+
if (!row.enabled) return false;
|
|
10
|
+
if (row.authHealth !== "ok") return false;
|
|
11
|
+
if (row.cooldownUntil && row.cooldownUntil > Date.now()) return false;
|
|
12
|
+
if (row.penaltyUntil && row.penaltyUntil > Date.now()) return false;
|
|
13
|
+
return true;
|
|
14
|
+
}).length;
|
|
15
|
+
|
|
16
|
+
return `oauth-router ${healthy}/${rows.length || 0} healthy | ${runtime.getPolicy()}`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function formatDuration(ms?: number): string {
|
|
20
|
+
if (!ms || ms <= 0) return "now";
|
|
21
|
+
if (ms < 1_000) return `${Math.round(ms)}ms`;
|
|
22
|
+
return `${Math.round(ms / 1_000)}s`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function truncate(text: string | undefined, max = 110): string {
|
|
26
|
+
if (!text) return "";
|
|
27
|
+
const clean = text.replace(/\s+/g, " ").trim();
|
|
28
|
+
return clean.length > max ? `${clean.slice(0, Math.max(0, max - 1))}…` : clean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function formatRoute(event: RouterUiEvent): string {
|
|
32
|
+
const parts = [event.accountLabel || event.accountId, event.upstreamId].filter(Boolean);
|
|
33
|
+
return parts.length ? parts.join(" @ ") : "router";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function formatActivityStatus(event: RouterUiEvent): string {
|
|
37
|
+
const route = formatRoute(event);
|
|
38
|
+
const model = event.modelId ? `${event.modelId} ` : "";
|
|
39
|
+
const reason = truncate(event.message, 70);
|
|
40
|
+
|
|
41
|
+
switch (event.phase) {
|
|
42
|
+
case "attempt": {
|
|
43
|
+
const retry = event.retryAttempt && event.maxRetries
|
|
44
|
+
? ` retry ${event.retryAttempt}/${event.maxRetries}`
|
|
45
|
+
: "";
|
|
46
|
+
return `oauth-router contacting ${model}via ${route}${retry}`;
|
|
47
|
+
}
|
|
48
|
+
case "retry":
|
|
49
|
+
return `oauth-router retry ${event.retryAttempt}/${event.maxRetries} in ${formatDuration(event.delayMs)} | ${reason || event.failureKind || "network error"}`;
|
|
50
|
+
case "failover":
|
|
51
|
+
return `oauth-router failover from ${route} | ${reason || event.failureKind || "upstream error"}`;
|
|
52
|
+
case "success":
|
|
53
|
+
return `oauth-router ok: ${model}via ${route}`;
|
|
54
|
+
case "error":
|
|
55
|
+
return `oauth-router error | ${reason || event.failureKind || "request failed"}`;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function notifyActivity(ctx: ExtensionContext, event: RouterUiEvent) {
|
|
60
|
+
if (event.phase === "attempt" || event.phase === "success") return;
|
|
61
|
+
|
|
62
|
+
const message = formatActivityStatus(event);
|
|
63
|
+
const level = event.phase === "error" ? "error" : "info";
|
|
64
|
+
ctx.ui.notify(message, level);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function installRouterUiBridge(pi: ExtensionAPI, runtime: RouterRuntime, notifyOnLoad = false) {
|
|
68
|
+
let activeCtx: ExtensionContext | undefined;
|
|
69
|
+
|
|
70
|
+
const setBaseStatus = (ctx: ExtensionContext) => {
|
|
71
|
+
activeCtx = ctx;
|
|
72
|
+
if (ctx.hasUI) ctx.ui.setStatus("oauth-router", getHealthSummary(runtime));
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
runtime.setUiReporter((event) => {
|
|
76
|
+
const ctx = activeCtx;
|
|
77
|
+
if (!ctx?.hasUI) return;
|
|
78
|
+
try {
|
|
79
|
+
ctx.ui.setStatus("oauth-router", formatActivityStatus(event));
|
|
80
|
+
notifyActivity(ctx, event);
|
|
81
|
+
} catch {
|
|
82
|
+
// Best-effort UI only; never disturb provider streaming.
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
87
|
+
setBaseStatus(ctx);
|
|
88
|
+
if (notifyOnLoad) ctx.ui.notify("oauth-router loaded", "info");
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
pi.on("agent_start", async (_event, ctx) => {
|
|
92
|
+
setBaseStatus(ctx);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
pi.on("turn_start", async (_event, ctx) => {
|
|
96
|
+
setBaseStatus(ctx);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
pi.on("turn_end", async (_event, ctx) => {
|
|
100
|
+
setBaseStatus(ctx);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
pi.on("agent_end", async (_event, ctx) => {
|
|
104
|
+
setBaseStatus(ctx);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
pi.on("session_shutdown", async () => {
|
|
108
|
+
activeCtx = undefined;
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export default function (pi: ExtensionAPI) {
|
|
113
|
+
const runtime = new RouterRuntime();
|
|
114
|
+
|
|
115
|
+
registerRouterProvider(pi, runtime);
|
|
116
|
+
registerRouterCommands(pi, runtime);
|
|
117
|
+
installRouterUiBridge(pi, runtime, false);
|
|
118
|
+
|
|
119
|
+
pi.registerCommand("router-debug-report", {
|
|
120
|
+
description: "Emit a detailed oauth-router report",
|
|
121
|
+
handler: async () => {
|
|
122
|
+
pi.sendMessage({
|
|
123
|
+
customType: "oauth-router",
|
|
124
|
+
content: formatStatusReport(runtime),
|
|
125
|
+
display: true,
|
|
126
|
+
details: { source: "oauth-router", debug: true },
|
|
127
|
+
});
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
}
|
|
@@ -25,6 +25,8 @@ import type {
|
|
|
25
25
|
RouterErrorMessageInput,
|
|
26
26
|
RouterModelConfig,
|
|
27
27
|
RouterStatusRow,
|
|
28
|
+
RouterUiEvent,
|
|
29
|
+
RouterUiReporter,
|
|
28
30
|
RouterUpstreamConfig,
|
|
29
31
|
RoutingPolicyName,
|
|
30
32
|
StoredRouterAccount,
|
|
@@ -176,6 +178,7 @@ export class RouterRuntime {
|
|
|
176
178
|
private config: RouterConfig;
|
|
177
179
|
private accounts: RouterAccountStore;
|
|
178
180
|
private state: RouterStateStore;
|
|
181
|
+
private uiReporter?: RouterUiReporter;
|
|
179
182
|
|
|
180
183
|
constructor() {
|
|
181
184
|
this.config = loadRouterConfig();
|
|
@@ -190,6 +193,18 @@ export class RouterRuntime {
|
|
|
190
193
|
this.state.pruneAccountIds(this.accounts.list().map((account) => account.id));
|
|
191
194
|
}
|
|
192
195
|
|
|
196
|
+
setUiReporter(reporter?: RouterUiReporter) {
|
|
197
|
+
this.uiReporter = reporter;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private emitUi(event: RouterUiEvent) {
|
|
201
|
+
try {
|
|
202
|
+
this.uiReporter?.(event);
|
|
203
|
+
} catch {
|
|
204
|
+
// UI updates must never affect model streaming or retry behavior.
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
193
208
|
getConfig(): RouterConfig {
|
|
194
209
|
this.reloadConfig();
|
|
195
210
|
return this.config;
|
|
@@ -468,17 +483,40 @@ export class RouterRuntime {
|
|
|
468
483
|
): Promise<{ completed: boolean; emittedMeaningfulOutput: boolean; failure?: FailureClassification }> {
|
|
469
484
|
for (let retryIndex = 0; ; retryIndex += 1) {
|
|
470
485
|
const result = await this.trySingleAccount(selection, outerStream, context, options);
|
|
486
|
+
const failure = result.failure;
|
|
471
487
|
const canRetry =
|
|
472
488
|
!result.completed &&
|
|
473
489
|
!result.emittedMeaningfulOutput &&
|
|
474
|
-
|
|
490
|
+
failure?.kind === "client-network" &&
|
|
475
491
|
retryIndex < this.config.clientNetworkMaxRetries;
|
|
476
492
|
|
|
477
|
-
if (!canRetry) return result;
|
|
493
|
+
if (!canRetry || !failure) return result;
|
|
478
494
|
|
|
479
495
|
const delayMs = this.getClientNetworkRetryDelayMs(retryIndex);
|
|
496
|
+
this.emitUi({
|
|
497
|
+
phase: "retry",
|
|
498
|
+
modelId,
|
|
499
|
+
accountId: selection.account.id,
|
|
500
|
+
accountLabel: selection.account.label,
|
|
501
|
+
upstreamId: selection.account.upstreamId,
|
|
502
|
+
failureKind: failure.kind,
|
|
503
|
+
status: failure.status,
|
|
504
|
+
message: failure.message,
|
|
505
|
+
retryAttempt: retryIndex + 1,
|
|
506
|
+
maxRetries: this.config.clientNetworkMaxRetries,
|
|
507
|
+
delayMs,
|
|
508
|
+
});
|
|
480
509
|
await sleep(delayMs, options?.signal);
|
|
481
510
|
this.state.markAttempt(selection.account.id, modelId);
|
|
511
|
+
this.emitUi({
|
|
512
|
+
phase: "attempt",
|
|
513
|
+
modelId,
|
|
514
|
+
accountId: selection.account.id,
|
|
515
|
+
accountLabel: selection.account.label,
|
|
516
|
+
upstreamId: selection.account.upstreamId,
|
|
517
|
+
retryAttempt: retryIndex + 2,
|
|
518
|
+
maxRetries: this.config.clientNetworkMaxRetries,
|
|
519
|
+
});
|
|
482
520
|
}
|
|
483
521
|
}
|
|
484
522
|
|
|
@@ -521,7 +559,11 @@ export class RouterRuntime {
|
|
|
521
559
|
reason: "aborted",
|
|
522
560
|
error: { ...event.error, stopReason: "aborted", errorMessage: message },
|
|
523
561
|
});
|
|
524
|
-
return {
|
|
562
|
+
return {
|
|
563
|
+
completed: true,
|
|
564
|
+
emittedMeaningfulOutput,
|
|
565
|
+
failure: { kind: "fatal", status: responseStatus, message },
|
|
566
|
+
};
|
|
525
567
|
}
|
|
526
568
|
|
|
527
569
|
const failure = classifyFailure(responseStatus, responseHeaders, message, this.config);
|
|
@@ -596,6 +638,13 @@ export class RouterRuntime {
|
|
|
596
638
|
const message = lastFailure
|
|
597
639
|
? `No healthy oauth-router accounts remaining after failover. Last error: ${lastFailure.message}`
|
|
598
640
|
: `No healthy oauth-router accounts are configured for model ${model.id}. Add accounts with /router-login add.`;
|
|
641
|
+
this.emitUi({
|
|
642
|
+
phase: "error",
|
|
643
|
+
modelId: model.id,
|
|
644
|
+
failureKind: lastFailure?.kind,
|
|
645
|
+
status: lastFailure?.status,
|
|
646
|
+
message,
|
|
647
|
+
});
|
|
599
648
|
outer.push({ type: "error", reason: "error", error: createErrorMessage({ model, message }) });
|
|
600
649
|
outer.end();
|
|
601
650
|
return;
|
|
@@ -604,6 +653,13 @@ export class RouterRuntime {
|
|
|
604
653
|
this.state.advanceCursor(policy, picked.nextCursor);
|
|
605
654
|
tried.add(picked.selected.account.id);
|
|
606
655
|
this.state.markAttempt(picked.selected.account.id, model.id);
|
|
656
|
+
this.emitUi({
|
|
657
|
+
phase: "attempt",
|
|
658
|
+
modelId: model.id,
|
|
659
|
+
accountId: picked.selected.account.id,
|
|
660
|
+
accountLabel: picked.selected.account.label,
|
|
661
|
+
upstreamId: picked.selected.account.upstreamId,
|
|
662
|
+
});
|
|
607
663
|
|
|
608
664
|
let selection: DelegateSelection;
|
|
609
665
|
try {
|
|
@@ -617,11 +673,39 @@ export class RouterRuntime {
|
|
|
617
673
|
}
|
|
618
674
|
lastFailure = { kind: "auth", status: 401, message };
|
|
619
675
|
this.markFailure(picked.selected.account.id, lastFailure);
|
|
676
|
+
this.emitUi({
|
|
677
|
+
phase: "failover",
|
|
678
|
+
modelId: model.id,
|
|
679
|
+
accountId: picked.selected.account.id,
|
|
680
|
+
accountLabel: picked.selected.account.label,
|
|
681
|
+
upstreamId: picked.selected.account.upstreamId,
|
|
682
|
+
failureKind: lastFailure.kind,
|
|
683
|
+
status: lastFailure.status,
|
|
684
|
+
message: lastFailure.message,
|
|
685
|
+
});
|
|
620
686
|
continue;
|
|
621
687
|
}
|
|
622
688
|
|
|
623
689
|
const result = await this.tryAccountWithClientNetworkRetries(selection, outer, context, model.id, options);
|
|
624
690
|
if (result.completed) {
|
|
691
|
+
this.emitUi(result.failure
|
|
692
|
+
? {
|
|
693
|
+
phase: "error",
|
|
694
|
+
modelId: model.id,
|
|
695
|
+
accountId: selection.account.id,
|
|
696
|
+
accountLabel: selection.account.label,
|
|
697
|
+
upstreamId: selection.account.upstreamId,
|
|
698
|
+
failureKind: result.failure.kind,
|
|
699
|
+
status: result.failure.status,
|
|
700
|
+
message: result.failure.message,
|
|
701
|
+
}
|
|
702
|
+
: {
|
|
703
|
+
phase: "success",
|
|
704
|
+
modelId: model.id,
|
|
705
|
+
accountId: selection.account.id,
|
|
706
|
+
accountLabel: selection.account.label,
|
|
707
|
+
upstreamId: selection.account.upstreamId,
|
|
708
|
+
});
|
|
625
709
|
outer.end();
|
|
626
710
|
return;
|
|
627
711
|
}
|
|
@@ -630,13 +714,41 @@ export class RouterRuntime {
|
|
|
630
714
|
lastFailure = result.failure;
|
|
631
715
|
|
|
632
716
|
if (emittedMeaningfulOutput) {
|
|
717
|
+
this.emitUi({
|
|
718
|
+
phase: "error",
|
|
719
|
+
modelId: model.id,
|
|
720
|
+
accountId: selection.account.id,
|
|
721
|
+
accountLabel: selection.account.label,
|
|
722
|
+
upstreamId: selection.account.upstreamId,
|
|
723
|
+
failureKind: lastFailure?.kind,
|
|
724
|
+
status: lastFailure?.status,
|
|
725
|
+
message: lastFailure?.message ?? "Upstream failed after partial output; failover is unsafe.",
|
|
726
|
+
});
|
|
633
727
|
outer.end();
|
|
634
728
|
return;
|
|
635
729
|
}
|
|
730
|
+
|
|
731
|
+
if (lastFailure) {
|
|
732
|
+
this.emitUi({
|
|
733
|
+
phase: "failover",
|
|
734
|
+
modelId: model.id,
|
|
735
|
+
accountId: selection.account.id,
|
|
736
|
+
accountLabel: selection.account.label,
|
|
737
|
+
upstreamId: selection.account.upstreamId,
|
|
738
|
+
failureKind: lastFailure.kind,
|
|
739
|
+
status: lastFailure.status,
|
|
740
|
+
message: lastFailure.message,
|
|
741
|
+
});
|
|
742
|
+
}
|
|
636
743
|
}
|
|
637
744
|
} catch (error) {
|
|
638
745
|
const message = error instanceof Error ? error.message : String(error);
|
|
639
746
|
const aborted = isAbortLike(message, options?.signal);
|
|
747
|
+
this.emitUi({
|
|
748
|
+
phase: "error",
|
|
749
|
+
modelId: model.id,
|
|
750
|
+
message: aborted ? "Request was aborted" : message,
|
|
751
|
+
});
|
|
640
752
|
outer.push({ type: "error", reason: aborted ? "aborted" : "error", error: createErrorMessage({ model, message, stopReason: aborted ? "aborted" : "error" }) });
|
|
641
753
|
outer.end();
|
|
642
754
|
}
|
|
@@ -231,6 +231,24 @@ export interface RouterStreamInput {
|
|
|
231
231
|
options?: SimpleStreamOptions;
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
+
export type RouterUiEventPhase = "attempt" | "retry" | "failover" | "success" | "error";
|
|
235
|
+
|
|
236
|
+
export interface RouterUiEvent {
|
|
237
|
+
phase: RouterUiEventPhase;
|
|
238
|
+
modelId?: string;
|
|
239
|
+
accountId?: string;
|
|
240
|
+
accountLabel?: string;
|
|
241
|
+
upstreamId?: string;
|
|
242
|
+
failureKind?: FailureClassification["kind"];
|
|
243
|
+
status?: number;
|
|
244
|
+
message?: string;
|
|
245
|
+
retryAttempt?: number;
|
|
246
|
+
maxRetries?: number;
|
|
247
|
+
delayMs?: number;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export type RouterUiReporter = (event: RouterUiEvent) => void;
|
|
251
|
+
|
|
234
252
|
export interface RouterErrorMessageInput {
|
|
235
253
|
model: Model<Api>;
|
|
236
254
|
message: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { Type } from "typebox";
|
|
3
3
|
import type { ContextManagerState } from "./state";
|
|
4
4
|
import { renderReport } from "./diagnostics";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { loadConfig, DEFAULT_CONFIG } from "./config";
|
|
3
3
|
import { createState } from "./state";
|
|
4
4
|
import { collectSkillsFromOptions, collectSkillsFromXml, mergeSkills } from "./skill-registry";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import type { ExtensionAPI } from "@
|
|
4
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
5
5
|
import type { ContextManagerState } from "./state";
|
|
6
6
|
import { recordBlocked } from "./state";
|
|
7
7
|
import { resolveTakomiRoutingPolicy } from "../takomi-runtime/routing-policy";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import type { ContextManagerConfig } from "./types";
|
|
3
3
|
import type { ContextManagerState } from "./state";
|
|
4
4
|
import { recordBlocked, syncReportLedger } from "./state";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import type { ExtensionAPI } from "@
|
|
3
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
4
4
|
import { Type } from "typebox";
|
|
5
5
|
import type { ContextManagerState } from "./state";
|
|
6
6
|
import { findSkill, normalizeName, sortedSkills } from "./skill-registry";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext } from "@
|
|
1
|
+
import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import type {
|
|
3
3
|
TakomiLaunchMode,
|
|
4
4
|
TakomiRole,
|