@llblab/pi-kit 0.35.1 → 0.35.3
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/BACKLOG.md +2 -0
- package/CHANGELOG.md +11 -0
- package/README.md +3 -3
- package/extensions/pi-actors/index.js +4 -0
- package/extensions/pi-claude-usage/index.ts +4 -0
- package/extensions/pi-clean-room/index.ts +4 -0
- package/extensions/pi-codex-usage/index.ts +4 -0
- package/extensions/pi-grow-loop/index.js +4 -0
- package/extensions/pi-state-flow/index.js +4 -0
- package/extensions/pi-telegram/index.js +4 -0
- package/node_modules/@llblab/pi-telegram/AGENTS.md +2 -1
- package/node_modules/@llblab/pi-telegram/BACKLOG.md +1 -11
- package/node_modules/@llblab/pi-telegram/CHANGELOG.md +12 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.d.ts +22 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.js +75 -16
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.d.ts +1 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.js +11 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/bus.js +30 -19
- package/node_modules/@llblab/pi-telegram/dist/lib/extension.js +21 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/logging.d.ts +36 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/logging.js +80 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/paths.d.ts +2 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/paths.js +18 -3
- package/node_modules/@llblab/pi-telegram/dist/lib/polling.d.ts +13 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/polling.js +33 -12
- package/node_modules/@llblab/pi-telegram/dist/lib/runtime.d.ts +11 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/runtime.js +31 -8
- package/node_modules/@llblab/pi-telegram/dist/lib/telegram-api.d.ts +2 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/telegram-api.js +2 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-reconciler.js +5 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/threads.d.ts +5 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/threads.js +3 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.d.ts +6 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.js +57 -12
- package/node_modules/@llblab/pi-telegram/dist/package.json +1 -1
- package/node_modules/@llblab/pi-telegram/docs/multi-instance-bus.md +3 -1
- package/node_modules/@llblab/pi-telegram/lib/bus-follower.ts +111 -15
- package/node_modules/@llblab/pi-telegram/lib/bus-leader.ts +15 -0
- package/node_modules/@llblab/pi-telegram/lib/bus.ts +30 -21
- package/node_modules/@llblab/pi-telegram/lib/extension.ts +21 -1
- package/node_modules/@llblab/pi-telegram/lib/logging.ts +122 -0
- package/node_modules/@llblab/pi-telegram/lib/paths.ts +22 -3
- package/node_modules/@llblab/pi-telegram/lib/polling.ts +44 -10
- package/node_modules/@llblab/pi-telegram/lib/runtime.ts +40 -7
- package/node_modules/@llblab/pi-telegram/lib/telegram-api.ts +8 -5
- package/node_modules/@llblab/pi-telegram/lib/thread-reconciler.ts +6 -1
- package/node_modules/@llblab/pi-telegram/lib/threads.ts +12 -5
- package/node_modules/@llblab/pi-telegram/lib/workspace-retirement.ts +69 -17
- package/node_modules/@llblab/pi-telegram/package.json +1 -1
- package/package.json +10 -9
|
@@ -6,6 +6,16 @@
|
|
|
6
6
|
|
|
7
7
|
import * as Machine from "./machine.ts";
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Structural port for run-collapsing diagnostics: a repeated identical failure extends its run instead of logging
|
|
11
|
+
* again, and the closing success records one outcome. The composition root owns the collapsed implementation.
|
|
12
|
+
*/
|
|
13
|
+
export interface TelegramRepeatedFailureLogPort {
|
|
14
|
+
record: (error: unknown, details?: Record<string, unknown>) => void;
|
|
15
|
+
settled: () => void;
|
|
16
|
+
reset: () => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
9
19
|
const TELEGRAM_TYPING_ACTION_INTERVAL_MS = 3_000;
|
|
10
20
|
const TELEGRAM_TYPING_IDLE_DRAIN_MAX_MS = 250;
|
|
11
21
|
|
|
@@ -344,6 +354,8 @@ function updateTelegramRuntimeStatusSafely<TContext>(
|
|
|
344
354
|
export interface TelegramTypingLoopStarterDeps<
|
|
345
355
|
TContext,
|
|
346
356
|
> extends TelegramRuntimeEventRecorderPort {
|
|
357
|
+
/** Collapses one sustained presence failure run; the caller supplies its owner. */
|
|
358
|
+
failureLog: TelegramRepeatedFailureLogPort;
|
|
347
359
|
typing: TelegramRuntimeTypingPort;
|
|
348
360
|
getDefaultChatId: () => number | undefined;
|
|
349
361
|
sendTypingAction: (
|
|
@@ -374,6 +386,31 @@ export function createTelegramTypingLoopStarter<TContext>(
|
|
|
374
386
|
threadId: number | undefined;
|
|
375
387
|
canContinue: () => boolean;
|
|
376
388
|
} | undefined;
|
|
389
|
+
// An unreachable transport repeats one identical presence failure every tick; the port collapses the run.
|
|
390
|
+
// Running it through one guard keeps a faulty diagnostics port from escaping the in-flight action owner.
|
|
391
|
+
const typingFailureLog: TelegramRepeatedFailureLogPort = {
|
|
392
|
+
record(error, details) {
|
|
393
|
+
try {
|
|
394
|
+
deps.failureLog.record(error, details);
|
|
395
|
+
} catch {
|
|
396
|
+
// Typing diagnostics cannot escape the in-flight action owner.
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
settled() {
|
|
400
|
+
try {
|
|
401
|
+
deps.failureLog.settled();
|
|
402
|
+
} catch {
|
|
403
|
+
// A successful presence outranks its own diagnostic.
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
reset() {
|
|
407
|
+
try {
|
|
408
|
+
deps.failureLog.reset();
|
|
409
|
+
} catch {
|
|
410
|
+
// Typing diagnostics cannot fail a loop stop.
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
};
|
|
377
414
|
return (ctx, chatId, options) => {
|
|
378
415
|
const sessionGeneration = deps.getSessionGeneration?.();
|
|
379
416
|
const transportAuthority = deps.getTransportAuthority?.();
|
|
@@ -422,24 +459,20 @@ export function createTelegramTypingLoopStarter<TContext>(
|
|
|
422
459
|
if (!active || !canContinue()) throw new Error("Typing context authority changed.");
|
|
423
460
|
},
|
|
424
461
|
});
|
|
462
|
+
typingFailureLog.settled();
|
|
425
463
|
} catch (error) {
|
|
426
464
|
if (!active) return;
|
|
427
465
|
if (!canContinue()) {
|
|
428
466
|
deps.typing.stop();
|
|
429
467
|
return;
|
|
430
468
|
}
|
|
431
|
-
|
|
432
|
-
deps.recordRuntimeEvent?.("typing", error, {
|
|
433
|
-
chatId: targetChatId,
|
|
434
|
-
});
|
|
435
|
-
} catch {
|
|
436
|
-
// Typing diagnostics cannot escape the in-flight action owner.
|
|
437
|
-
}
|
|
469
|
+
typingFailureLog.record(error, { chatId: targetChatId });
|
|
438
470
|
}
|
|
439
471
|
},
|
|
440
472
|
shouldContinue: canContinue,
|
|
441
473
|
onStopped: () => {
|
|
442
474
|
active = false;
|
|
475
|
+
typingFailureLog.reset();
|
|
443
476
|
if (currentOwner === owner) currentOwner = undefined;
|
|
444
477
|
},
|
|
445
478
|
});
|
|
@@ -401,6 +401,8 @@ export interface TelegramApiCallOptions {
|
|
|
401
401
|
sleep?: (ms: number) => Promise<void>;
|
|
402
402
|
/** Observability hook fired before a 429 retry wait, never for 5xx waits. */
|
|
403
403
|
onRetryWait?: (wait: TelegramApiRetryWait) => void;
|
|
404
|
+
/** Caller-owned expected failure: still thrown, but the caller records the outcome instead of the API log. */
|
|
405
|
+
isExpectedError?: (error: unknown) => boolean;
|
|
404
406
|
}
|
|
405
407
|
|
|
406
408
|
export class TelegramApiAuthorityError extends Error {
|
|
@@ -2197,11 +2199,12 @@ export function createTelegramBridgeApiRuntime(
|
|
|
2197
2199
|
) {
|
|
2198
2200
|
return true as TResponse;
|
|
2199
2201
|
}
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2202
|
+
if (!options?.isExpectedError?.(error))
|
|
2203
|
+
deps.recordRuntimeEvent(
|
|
2204
|
+
"api",
|
|
2205
|
+
error,
|
|
2206
|
+
withTelegramTransportDiagnostics(error, { method }),
|
|
2207
|
+
);
|
|
2205
2208
|
throw error;
|
|
2206
2209
|
}
|
|
2207
2210
|
};
|
|
@@ -719,7 +719,12 @@ export async function applyThreadReconciliationPlan(
|
|
|
719
719
|
}
|
|
720
720
|
let deleteConfirmed = false;
|
|
721
721
|
let superseded = false;
|
|
722
|
-
|
|
722
|
+
// Private-chat topics (positive chat ids) cannot be closed; Telegram only supports closeForumTopic in forums.
|
|
723
|
+
const skipClose =
|
|
724
|
+
ports.skipCloseBeforeDelete ||
|
|
725
|
+
(action.kind === "close-delete-graceful-shutdown-topic" &&
|
|
726
|
+
action.target.chatId > 0);
|
|
727
|
+
for (const method of skipClose
|
|
723
728
|
? ["deleteForumTopic"]
|
|
724
729
|
: ["closeForumTopic", "deleteForumTopic"]) {
|
|
725
730
|
if (ports.isCleanupTargetProtected?.(action.target, action)) {
|
|
@@ -252,6 +252,13 @@ export interface TelegramWorkspaceExternalProtectionEvidence {
|
|
|
252
252
|
deliveryAuthority: TelegramWorkspaceProtectionState;
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
+
/** Per-binding probe; `withSnapshot` lets one occupancy capture share binding-independent evidence reads. */
|
|
256
|
+
export type TelegramWorkspaceExternalProtectionCapture = ((
|
|
257
|
+
binding: TelegramWorkspaceThreadBinding,
|
|
258
|
+
) => TelegramWorkspaceExternalProtectionEvidence) & {
|
|
259
|
+
withSnapshot?: <T>(capture: () => T) => T;
|
|
260
|
+
};
|
|
261
|
+
|
|
255
262
|
export interface TelegramWorkspaceSlotOccupancySnapshot {
|
|
256
263
|
bindings: TelegramWorkspaceSlotOccupancy[];
|
|
257
264
|
reservedSlots: string[];
|
|
@@ -876,9 +883,7 @@ export interface TelegramTopicTargetStore {
|
|
|
876
883
|
) => Promise<boolean>;
|
|
877
884
|
/** Caller must separately prove no external live owner, accepted work, or delivery authority. */
|
|
878
885
|
captureWorkspaceSlotOccupancy: (
|
|
879
|
-
getExternalProtection:
|
|
880
|
-
binding: TelegramWorkspaceThreadBinding,
|
|
881
|
-
) => TelegramWorkspaceExternalProtectionEvidence,
|
|
886
|
+
getExternalProtection: TelegramWorkspaceExternalProtectionCapture,
|
|
882
887
|
options?: { expectedRetirement?: TelegramWorkspaceRetirementIntent },
|
|
883
888
|
) => TelegramWorkspaceSlotOccupancySnapshot;
|
|
884
889
|
hasWorkspaceBinding: (cwd: string, sessionId?: string) => boolean;
|
|
@@ -7359,7 +7364,9 @@ export function createTelegramTopicTargetStore(
|
|
|
7359
7364
|
},
|
|
7360
7365
|
captureWorkspaceSlotOccupancy(getExternalProtection, options) {
|
|
7361
7366
|
const nowMs = getNowMs();
|
|
7362
|
-
const
|
|
7367
|
+
const inSnapshot =
|
|
7368
|
+
getExternalProtection.withSnapshot ?? ((capture) => capture());
|
|
7369
|
+
const bindings = inSnapshot(() => Array.from(workspaceBindings.values()).map((binding) => {
|
|
7363
7370
|
const slot = binding.slot?.toLowerCase() ?? "";
|
|
7364
7371
|
const locallyProtected = isWorkspaceBindingLocallyProtected(
|
|
7365
7372
|
binding,
|
|
@@ -7398,7 +7405,7 @@ export function createTelegramTopicTargetStore(
|
|
|
7398
7405
|
: {}),
|
|
7399
7406
|
protection,
|
|
7400
7407
|
};
|
|
7401
|
-
});
|
|
7408
|
+
}));
|
|
7402
7409
|
const localReservedSlots = [
|
|
7403
7410
|
...Array.from(workspaceClaims.values()).map(
|
|
7404
7411
|
(claim) => claim.identity.slot,
|
|
@@ -146,6 +146,8 @@ export function captureTelegramWorkspaceJournalProtectionSources(input: {
|
|
|
146
146
|
path: string,
|
|
147
147
|
) => () => TelegramWorkspaceJournalReader | undefined;
|
|
148
148
|
};
|
|
149
|
+
/** Snapshot-scoped reuse of binding-independent (shared/discovered) source reads. */
|
|
150
|
+
sharedSourceReads?: Map<string, TelegramWorkspaceJournalProtectionSource>;
|
|
149
151
|
}): TelegramWorkspaceJournalProtectionCapture {
|
|
150
152
|
const sources: TelegramWorkspaceJournalProtectionSource[] = [];
|
|
151
153
|
let complete =
|
|
@@ -155,26 +157,43 @@ export function captureTelegramWorkspaceJournalProtectionSources(input: {
|
|
|
155
157
|
scope: TelegramWorkspaceJournalProtectionSource["scope"],
|
|
156
158
|
resolve: () => TelegramWorkspaceJournalReader | undefined,
|
|
157
159
|
): void => {
|
|
160
|
+
const sharedKey =
|
|
161
|
+
scope.kind === "shared"
|
|
162
|
+
? "shared"
|
|
163
|
+
: scope.kind === "discovered"
|
|
164
|
+
? `discovered:${scope.path}`
|
|
165
|
+
: undefined;
|
|
166
|
+
let source =
|
|
167
|
+
sharedKey === undefined
|
|
168
|
+
? undefined
|
|
169
|
+
: input.sharedSourceReads?.get(sharedKey);
|
|
170
|
+
if (!source) {
|
|
171
|
+
source = readSource(scope, resolve);
|
|
172
|
+
if (sharedKey !== undefined)
|
|
173
|
+
input.sharedSourceReads?.set(sharedKey, source);
|
|
174
|
+
}
|
|
175
|
+
if (source.kind === "unknown") complete = false;
|
|
176
|
+
sources.push(source);
|
|
177
|
+
};
|
|
178
|
+
const readSource = (
|
|
179
|
+
scope: TelegramWorkspaceJournalProtectionSource["scope"],
|
|
180
|
+
resolve: () => TelegramWorkspaceJournalReader | undefined,
|
|
181
|
+
): TelegramWorkspaceJournalProtectionSource => {
|
|
158
182
|
try {
|
|
159
183
|
const binding = resolve();
|
|
160
|
-
if (!binding) {
|
|
161
|
-
complete = false;
|
|
162
|
-
sources.push({ kind: "unknown", scope });
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
184
|
+
if (!binding) return { kind: "unknown", scope };
|
|
165
185
|
const read = binding.readForProtection ?? binding.journal.read;
|
|
166
186
|
const snapshot = input.withJournalReference
|
|
167
187
|
? input.withJournalReference(binding, read)
|
|
168
188
|
: read();
|
|
169
|
-
|
|
189
|
+
return {
|
|
170
190
|
kind: "available",
|
|
171
191
|
scope,
|
|
172
192
|
entries: snapshot.entries,
|
|
173
193
|
...(snapshot.exists === undefined ? {} : { exists: snapshot.exists }),
|
|
174
|
-
}
|
|
194
|
+
};
|
|
175
195
|
} catch {
|
|
176
|
-
|
|
177
|
-
sources.push({ kind: "unknown", scope });
|
|
196
|
+
return { kind: "unknown", scope };
|
|
178
197
|
}
|
|
179
198
|
};
|
|
180
199
|
capture({ kind: "shared" }, input.resolveLeader);
|
|
@@ -586,10 +605,12 @@ interface TelegramWorkspaceProtectionObserverDeps {
|
|
|
586
605
|
}
|
|
587
606
|
|
|
588
607
|
export interface TelegramWorkspaceProtectionObserver {
|
|
589
|
-
capture: (
|
|
608
|
+
capture: ((
|
|
590
609
|
binding: TelegramWorkspaceThreadBinding,
|
|
591
610
|
options?: { requireBindingProvenance?: boolean },
|
|
592
|
-
) => TelegramWorkspaceExternalProtectionEvidence
|
|
611
|
+
) => TelegramWorkspaceExternalProtectionEvidence) & {
|
|
612
|
+
withSnapshot?: <T>(capture: () => T) => T;
|
|
613
|
+
};
|
|
593
614
|
captureJournalSources: (
|
|
594
615
|
binding: TelegramWorkspaceThreadBinding,
|
|
595
616
|
) => TelegramWorkspaceJournalProtectionCapture;
|
|
@@ -602,9 +623,39 @@ export interface TelegramWorkspaceProtectionObserver {
|
|
|
602
623
|
export function createTelegramWorkspaceProtectionObserver(
|
|
603
624
|
deps: TelegramWorkspaceProtectionObserverDeps,
|
|
604
625
|
): TelegramWorkspaceProtectionObserver {
|
|
626
|
+
// One occupancy snapshot probes every binding synchronously; namespace and shared/discovered
|
|
627
|
+
// journal reads are binding-independent, so read them once per snapshot instead of per binding.
|
|
628
|
+
// Never widen this beyond one synchronous capture: post-fence rechecks need fresh evidence.
|
|
629
|
+
let snapshot:
|
|
630
|
+
| {
|
|
631
|
+
namespace?: { value?: TelegramJournalNamespaceInspection; error?: unknown };
|
|
632
|
+
reads: Map<string, TelegramWorkspaceJournalProtectionSource>;
|
|
633
|
+
}
|
|
634
|
+
| undefined;
|
|
635
|
+
const inspectNamespace = (): TelegramJournalNamespaceInspection | undefined => {
|
|
636
|
+
if (!snapshot) return deps.inspectJournalNamespace?.();
|
|
637
|
+
if (!snapshot.namespace) {
|
|
638
|
+
try {
|
|
639
|
+
snapshot.namespace = { value: deps.inspectJournalNamespace?.() };
|
|
640
|
+
} catch (error) {
|
|
641
|
+
snapshot.namespace = { error };
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
if ("error" in snapshot.namespace) throw snapshot.namespace.error;
|
|
645
|
+
return snapshot.namespace.value;
|
|
646
|
+
};
|
|
647
|
+
const withSnapshot = <T>(run: () => T): T => {
|
|
648
|
+
if (snapshot) return run();
|
|
649
|
+
snapshot = { reads: new Map() };
|
|
650
|
+
try {
|
|
651
|
+
return run();
|
|
652
|
+
} finally {
|
|
653
|
+
snapshot = undefined;
|
|
654
|
+
}
|
|
655
|
+
};
|
|
605
656
|
const captureJournalSources: TelegramWorkspaceProtectionObserver["captureJournalSources"] =
|
|
606
657
|
(candidate) => {
|
|
607
|
-
const namespace =
|
|
658
|
+
const namespace = inspectNamespace();
|
|
608
659
|
if (
|
|
609
660
|
deps.inspectJournalNamespace &&
|
|
610
661
|
(!namespace ||
|
|
@@ -658,12 +709,13 @@ export function createTelegramWorkspaceProtectionObserver(
|
|
|
658
709
|
},
|
|
659
710
|
}
|
|
660
711
|
: {}),
|
|
712
|
+
...(snapshot ? { sharedSourceReads: snapshot.reads } : {}),
|
|
661
713
|
});
|
|
662
714
|
};
|
|
663
|
-
const
|
|
664
|
-
binding,
|
|
665
|
-
options,
|
|
666
|
-
) {
|
|
715
|
+
const captureOne = function (
|
|
716
|
+
binding: TelegramWorkspaceThreadBinding,
|
|
717
|
+
options?: { requireBindingProvenance?: boolean },
|
|
718
|
+
): TelegramWorkspaceExternalProtectionEvidence {
|
|
667
719
|
return captureTelegramWorkspaceExternalProtection({
|
|
668
720
|
binding,
|
|
669
721
|
requireBindingProvenance: options?.requireBindingProvenance,
|
|
@@ -714,7 +766,7 @@ export function createTelegramWorkspaceProtectionObserver(
|
|
|
714
766
|
});
|
|
715
767
|
};
|
|
716
768
|
return {
|
|
717
|
-
capture,
|
|
769
|
+
capture: Object.assign(captureOne, { withSnapshot }),
|
|
718
770
|
captureJournalSources,
|
|
719
771
|
getJournalWriterProtection:
|
|
720
772
|
deps.getJournalWriterProtection ?? (() => "unknown"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llblab/pi-kit",
|
|
3
|
-
"version": "0.35.
|
|
3
|
+
"version": "0.35.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"validate": "npm test && npm run audit && npm run pack:check"
|
|
34
34
|
},
|
|
35
35
|
"files": [
|
|
36
|
+
"extensions/",
|
|
36
37
|
"README.md",
|
|
37
38
|
"AGENTS.md",
|
|
38
39
|
"BACKLOG.md",
|
|
@@ -47,7 +48,7 @@
|
|
|
47
48
|
"@llblab/pi-codex-usage": "0.13.1",
|
|
48
49
|
"@llblab/pi-grow-loop": "0.9.0",
|
|
49
50
|
"@llblab/pi-state-flow": "0.26.4",
|
|
50
|
-
"@llblab/pi-telegram": "0.57.
|
|
51
|
+
"@llblab/pi-telegram": "0.57.2",
|
|
51
52
|
"@llblab/skills": "1.15.0"
|
|
52
53
|
},
|
|
53
54
|
"bundledDependencies": [
|
|
@@ -62,13 +63,13 @@
|
|
|
62
63
|
],
|
|
63
64
|
"pi": {
|
|
64
65
|
"extensions": [
|
|
65
|
-
"./
|
|
66
|
-
"./
|
|
67
|
-
"./
|
|
68
|
-
"./
|
|
69
|
-
"./
|
|
70
|
-
"./
|
|
71
|
-
"./
|
|
66
|
+
"./extensions/pi-actors/index.js",
|
|
67
|
+
"./extensions/pi-claude-usage/index.ts",
|
|
68
|
+
"./extensions/pi-clean-room/index.ts",
|
|
69
|
+
"./extensions/pi-codex-usage/index.ts",
|
|
70
|
+
"./extensions/pi-grow-loop/index.js",
|
|
71
|
+
"./extensions/pi-state-flow/index.js",
|
|
72
|
+
"./extensions/pi-telegram/index.js"
|
|
72
73
|
],
|
|
73
74
|
"skills": [
|
|
74
75
|
"./node_modules/@llblab/pi-actors/dist/skills",
|