@gkzhb/pi-roles 0.2.4-beta.1 → 0.2.4-beta.2
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 +6 -2
- package/dist/index.d.ts +87 -16
- package/dist/index.js +124 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -186,7 +186,11 @@ By default, a normal new conversation resolves its role again from `--role`, `PI
|
|
|
186
186
|
{ "pi-roles": { "preserveRoleOnNewSession": true } }
|
|
187
187
|
```
|
|
188
188
|
|
|
189
|
-
|
|
189
|
+
A normal replacement reads the old session file. **Before the first assistant
|
|
190
|
+
response, Pi deliberately has not created that file yet**; during that narrow
|
|
191
|
+
case pi-roles transfers the active role through a process-local snapshot taken
|
|
192
|
+
at `session_before_switch`. The replacement instance consumes that snapshot
|
|
193
|
+
once. This fallback does not persist roles across a Pi restart.
|
|
190
194
|
|
|
191
195
|
---
|
|
192
196
|
|
|
@@ -295,7 +299,7 @@ If you have Pi's [auto-reload](https://github.com/badlogic/pi-mono/blob/main/pac
|
|
|
295
299
|
|---|---|---|
|
|
296
300
|
| `roleScope` | `"both"` | Discovery scope. `"user"`, `"project"`, or `"both"`. |
|
|
297
301
|
| `defaultRole` | `"role-assistant"` | Role applied at session start when no `--role` or `PI_ROLE`. |
|
|
298
|
-
| `preserveRoleOnNewSession` | `false` | Keep the
|
|
302
|
+
| `preserveRoleOnNewSession` | `false` | Keep the prior session's active role when creating a normal new conversation. Does not apply across restarts or to explicit `/role <name> --reset`. |
|
|
299
303
|
| `intercomMode` | `"off"` | Default intercom behavior for roles that don't set it explicitly. |
|
|
300
304
|
| `titleModel` | `null` (auto) | Model used for session-intent summarization. Its API key and request headers are resolved from Pi's model registry, including `models.json` environment-variable configuration. Falls back to the session's current model. |
|
|
301
305
|
| `warnOnMissingMcp` | `true` | Whether to surface a warning when a role's `mcp:*` entry can't be resolved. |
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ExtensionAPI } from '@mariozechner/pi-coding-agent';
|
|
1
|
+
import { ExtensionAPI, SessionEntry } from '@mariozechner/pi-coding-agent';
|
|
2
2
|
import { AutocompleteItem } from '@mariozechner/pi-tui';
|
|
3
3
|
import { Static, Type } from 'typebox';
|
|
4
4
|
|
|
@@ -192,6 +192,50 @@ declare const PiRolesSettingsSchema: Type.TObject<{
|
|
|
192
192
|
warnOnMissingMcp: Type.TOptional<Type.TBoolean>;
|
|
193
193
|
}>;
|
|
194
194
|
type PiRolesSettings = Static<typeof PiRolesSettingsSchema>;
|
|
195
|
+
/**
|
|
196
|
+
* State persisted via `pi.appendEntry("pi-roles:active-role", ...)`. Read on
|
|
197
|
+
* `session_start` (with reason="reload" or "resume") to restore the active
|
|
198
|
+
* role after a reload, since extension memory is wiped on /reload.
|
|
199
|
+
*
|
|
200
|
+
* `appliedAt` is the leaf role's source/path so we can re-resolve the chain
|
|
201
|
+
* fresh on restore — the extends parents may have been edited in the
|
|
202
|
+
* meantime.
|
|
203
|
+
*
|
|
204
|
+
* `intent` carries the session-intent summary we generated for the title, so
|
|
205
|
+
* a /role swap mid-session can keep the intent and just replace the role
|
|
206
|
+
* prefix in the session name without re-summarizing.
|
|
207
|
+
*/
|
|
208
|
+
declare const ActiveRoleStateSchema: Type.TObject<{
|
|
209
|
+
name: Type.TString;
|
|
210
|
+
/** Source of the LEAF role file when it was applied. */
|
|
211
|
+
source: Type.TUnion<[Type.TLiteral<"project">, Type.TLiteral<"user">, Type.TLiteral<"built-in">]>;
|
|
212
|
+
/** Path of the LEAF role file. */
|
|
213
|
+
path: Type.TString;
|
|
214
|
+
/** Cached session-intent summary for the title. May be empty pre-first-message. */
|
|
215
|
+
intent: Type.TOptional<Type.TString>;
|
|
216
|
+
/** Unix ms timestamp; for diagnostics only. */
|
|
217
|
+
appliedAt: Type.TNumber;
|
|
218
|
+
}>;
|
|
219
|
+
type ActiveRoleState = Static<typeof ActiveRoleStateSchema>;
|
|
220
|
+
interface ResetRoleRequest {
|
|
221
|
+
/** Name explicitly requested by `/role <name> --reset`. */
|
|
222
|
+
name: string;
|
|
223
|
+
/** Unix ms timestamp, retained for diagnostics. */
|
|
224
|
+
requestedAt: number;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* State a replacement session may inherit from the previous session.
|
|
229
|
+
*
|
|
230
|
+
* Persisted session entries are authoritative. This process-local state only
|
|
231
|
+
* bridges Pi's pre-first-assistant-response gap, during which the old session
|
|
232
|
+
* has entries in memory but no session file on disk yet.
|
|
233
|
+
*/
|
|
234
|
+
interface PreviousSessionRoleState {
|
|
235
|
+
activeRole: ActiveRoleState | undefined;
|
|
236
|
+
/** Present only when the final reset lifecycle event is a valid request. */
|
|
237
|
+
pendingResetRole: ResetRoleRequest | undefined;
|
|
238
|
+
}
|
|
195
239
|
|
|
196
240
|
/**
|
|
197
241
|
* pi-roles extension entry point.
|
|
@@ -200,12 +244,13 @@ type PiRolesSettings = Static<typeof PiRolesSettingsSchema>;
|
|
|
200
244
|
* (settings.ts) into the three Pi integration points the role lifecycle
|
|
201
245
|
* actually needs:
|
|
202
246
|
*
|
|
203
|
-
* - `session_start` — restore
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
* session
|
|
208
|
-
* instance
|
|
247
|
+
* - `session_start` — restore the current session's persisted role on
|
|
248
|
+
* reload/resume. For a new session, resolve an explicit persisted reset
|
|
249
|
+
* request first, then (when configured) preserve the previous session's
|
|
250
|
+
* active role, otherwise use --role > PI_ROLE > defaultRole > built-in.
|
|
251
|
+
* New-session transfer reads `previousSessionFile`; Pi recreates the
|
|
252
|
+
* extension instance during session replacement, so in-memory state is
|
|
253
|
+
* intentionally never used as a cross-session handoff.
|
|
209
254
|
* - `before_agent_start` — re-inject the active role's body as the system
|
|
210
255
|
* prompt every turn (Pi rebuilds the prompt per turn; this is the
|
|
211
256
|
* stable hook).
|
|
@@ -221,8 +266,12 @@ type PiRolesSettings = Static<typeof PiRolesSettingsSchema>;
|
|
|
221
266
|
interface RuntimeState {
|
|
222
267
|
/** Live role applied to this session, or null before first apply. */
|
|
223
268
|
activeRole: ResolvedRole | null;
|
|
224
|
-
/**
|
|
225
|
-
|
|
269
|
+
/**
|
|
270
|
+
* Explicit reset requested in this still-live instance. It is copied into
|
|
271
|
+
* the process bridge by session_before_switch, then read by the replacement
|
|
272
|
+
* instance if Pi has not yet created the old session file.
|
|
273
|
+
*/
|
|
274
|
+
pendingResetRequest: ResetRoleRequest | undefined;
|
|
226
275
|
/** Cached discovery result; refreshed on session_start, every `/role` invocation, and `/role reload`. */
|
|
227
276
|
roles: RawRole[];
|
|
228
277
|
/** Shadowed roles found at lower-precedence scopes; shown in `/role list`. */
|
|
@@ -265,15 +314,15 @@ declare function composeSystemPrompt(state: Pick<RuntimeState, "activeRole" | "s
|
|
|
265
314
|
systemPrompt: string;
|
|
266
315
|
} | undefined;
|
|
267
316
|
/**
|
|
268
|
-
* Pick the role for an ordinary new conversation.
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
* this helper is reached.
|
|
317
|
+
* Pick the role for an ordinary new conversation. `activeRole` must come
|
|
318
|
+
* from the previous session's persisted state, not the current extension
|
|
319
|
+
* instance: Pi recreates extensions for `/new`. An explicit --reset role is
|
|
320
|
+
* resolved before this helper is reached.
|
|
272
321
|
*/
|
|
273
322
|
declare function pickNewSessionRoleName(activeRole: Pick<ResolvedRole, "name"> | null, pi: ExtensionAPI, settings: PiRolesSettings, roles: RawRole[]): string;
|
|
274
323
|
/**
|
|
275
|
-
* Pick the role to launch with on a fresh session_start (no
|
|
276
|
-
*
|
|
324
|
+
* Pick the role to launch with on a fresh session_start (no persisted
|
|
325
|
+
* previous-session override). Precedence per BUILD-STATUS.md:
|
|
277
326
|
*
|
|
278
327
|
* --role flag > PI_ROLE env > settings.defaultRole > built-in role-assistant
|
|
279
328
|
*
|
|
@@ -282,10 +331,32 @@ declare function pickNewSessionRoleName(activeRole: Pick<ResolvedRole, "name"> |
|
|
|
282
331
|
* of the session.
|
|
283
332
|
*/
|
|
284
333
|
declare function pickInitialRoleName(pi: ExtensionAPI, settings: PiRolesSettings, roles: RawRole[]): string;
|
|
334
|
+
/**
|
|
335
|
+
* Prefer durable state from the previous session log. The process-local
|
|
336
|
+
* transfer is only a fallback for Pi's pre-first-response persistence gap.
|
|
337
|
+
*/
|
|
338
|
+
declare function pickPreviousSessionRoleState(diskState: PreviousSessionRoleState | undefined, processState: PreviousSessionRoleState | undefined): PreviousSessionRoleState | undefined;
|
|
339
|
+
/**
|
|
340
|
+
* Read transferable state from an earlier session file. Session files may be
|
|
341
|
+
* missing, corrupted, or unavailable in ephemeral modes; those cases simply
|
|
342
|
+
* disable inheritance and fall back to ordinary initial resolution.
|
|
343
|
+
*/
|
|
344
|
+
declare function findPreviousSessionRoleState(previousSessionFile: string | undefined): PreviousSessionRoleState | undefined;
|
|
345
|
+
/**
|
|
346
|
+
* Interpret entries from a previous session for a fresh `reason="new"`
|
|
347
|
+
* session. Exported as a pure test seam: the runtime reader above only opens
|
|
348
|
+
* the file, while this function contains the lifecycle semantics.
|
|
349
|
+
*
|
|
350
|
+
* Reset events are intentionally an ordered two-event protocol without a
|
|
351
|
+
* requestId. The final reset lifecycle event is authoritative: cancellation
|
|
352
|
+
* suppresses every earlier request; a valid final request overrides ordinary
|
|
353
|
+
* role preservation.
|
|
354
|
+
*/
|
|
355
|
+
declare function resolvePreviousSessionRoleState(entries: readonly SessionEntry[]): PreviousSessionRoleState;
|
|
285
356
|
/**
|
|
286
357
|
* Provide tab completions for `/role <here>`. Combines built-in subcommands
|
|
287
358
|
* with discovered role names; case-insensitive prefix match.
|
|
288
359
|
*/
|
|
289
360
|
declare function roleCompletions(prefix: string, roles: RawRole[]): AutocompleteItem[] | null;
|
|
290
361
|
|
|
291
|
-
export { composeSystemPrompt, export_default as default, pickInitialRoleName, pickNewSessionRoleName, roleCompletions };
|
|
362
|
+
export { composeSystemPrompt, export_default as default, findPreviousSessionRoleState, pickInitialRoleName, pickNewSessionRoleName, pickPreviousSessionRoleState, resolvePreviousSessionRoleState, roleCompletions };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import {
|
|
3
|
+
SessionManager
|
|
4
|
+
} from "@mariozechner/pi-coding-agent";
|
|
5
|
+
|
|
1
6
|
// src/schemas.ts
|
|
2
7
|
import { Type } from "typebox";
|
|
3
8
|
var ThinkingLevelSchema = Type.Union(
|
|
@@ -120,6 +125,8 @@ var ActiveRoleStateSchema = Type.Object(
|
|
|
120
125
|
{ additionalProperties: false }
|
|
121
126
|
);
|
|
122
127
|
var ACTIVE_ROLE_ENTRY_TYPE = "pi-roles:active-role";
|
|
128
|
+
var RESET_ROLE_REQUEST_ENTRY_TYPE = "pi-roles:reset-role-request";
|
|
129
|
+
var RESET_ROLE_CANCELLED_ENTRY_TYPE = "pi-roles:reset-role-cancelled";
|
|
123
130
|
var ROLE_NOTIFICATION_MESSAGE_TYPE = "pi-roles:notification";
|
|
124
131
|
var STATUS_KEY = "pi-roles";
|
|
125
132
|
var BUILTIN_ROLE_ASSISTANT_NAME = "role-assistant";
|
|
@@ -712,6 +719,26 @@ async function generateAndApplyTitle(args) {
|
|
|
712
719
|
}
|
|
713
720
|
}
|
|
714
721
|
|
|
722
|
+
// src/utils/process-transfer.ts
|
|
723
|
+
var PROCESS_TRANSFER_KEY = /* @__PURE__ */ Symbol.for("pi-roles.previous-session-transfer");
|
|
724
|
+
function getStore() {
|
|
725
|
+
const root = globalThis;
|
|
726
|
+
return root[PROCESS_TRANSFER_KEY] ??= /* @__PURE__ */ new Map();
|
|
727
|
+
}
|
|
728
|
+
function storeProcessTransfer(sessionFile, state) {
|
|
729
|
+
if (sessionFile) getStore().set(sessionFile, state);
|
|
730
|
+
}
|
|
731
|
+
function takeProcessTransfer(sessionFile) {
|
|
732
|
+
if (!sessionFile) return void 0;
|
|
733
|
+
const store = getStore();
|
|
734
|
+
const state = store.get(sessionFile);
|
|
735
|
+
store.delete(sessionFile);
|
|
736
|
+
return state;
|
|
737
|
+
}
|
|
738
|
+
function discardProcessTransfer(sessionFile) {
|
|
739
|
+
if (sessionFile) getStore().delete(sessionFile);
|
|
740
|
+
}
|
|
741
|
+
|
|
715
742
|
// src/index.ts
|
|
716
743
|
var FLAG_NAME = "role";
|
|
717
744
|
var ENV_VAR = "PI_ROLE";
|
|
@@ -719,7 +746,7 @@ var SUBCOMMANDS = ["list", "current", "reload"];
|
|
|
719
746
|
function index_default(pi) {
|
|
720
747
|
const state = {
|
|
721
748
|
activeRole: null,
|
|
722
|
-
|
|
749
|
+
pendingResetRequest: void 0,
|
|
723
750
|
roles: [],
|
|
724
751
|
shadowed: [],
|
|
725
752
|
settings: {},
|
|
@@ -740,22 +767,42 @@ function index_default(pi) {
|
|
|
740
767
|
pi.registerMessageRenderer(ROLE_NOTIFICATION_MESSAGE_TYPE, () => {
|
|
741
768
|
return void 0;
|
|
742
769
|
});
|
|
770
|
+
pi.on("session_before_switch", (event, ctx) => {
|
|
771
|
+
if (event.reason !== "new") return;
|
|
772
|
+
storeProcessTransfer(ctx.sessionManager.getSessionFile(), {
|
|
773
|
+
activeRole: state.activeRole ? activeRoleStateFromResolved(state.activeRole, state.intent) : void 0,
|
|
774
|
+
pendingResetRole: state.pendingResetRequest
|
|
775
|
+
});
|
|
776
|
+
});
|
|
743
777
|
pi.on("session_start", async (event, ctx) => {
|
|
744
778
|
refreshFromDisk(ctx.cwd);
|
|
745
779
|
const restored = findRestoredState(ctx);
|
|
746
|
-
|
|
780
|
+
const diskPrevious = event.reason === "new" ? findPreviousSessionRoleState(event.previousSessionFile) : void 0;
|
|
781
|
+
const memoryPrevious = event.reason === "new" ? takeProcessTransfer(event.previousSessionFile) : void 0;
|
|
782
|
+
const previous = pickPreviousSessionRoleState(diskPrevious, memoryPrevious);
|
|
783
|
+
debugLog("index", `session_start reason=${event.reason}`, {
|
|
784
|
+
restored: restored ? { name: restored.name, intent: restored.intent } : void 0,
|
|
785
|
+
previousActiveRole: previous?.activeRole?.name,
|
|
786
|
+
previousResetRole: previous?.pendingResetRole?.name
|
|
787
|
+
});
|
|
747
788
|
let targetName;
|
|
748
789
|
let preservedIntent;
|
|
749
790
|
let silent = false;
|
|
750
|
-
if (
|
|
751
|
-
targetName = state.pendingRoleAfterReset;
|
|
752
|
-
state.pendingRoleAfterReset = null;
|
|
753
|
-
} else if ((event.reason === "reload" || event.reason === "resume") && restored) {
|
|
791
|
+
if ((event.reason === "reload" || event.reason === "resume") && restored) {
|
|
754
792
|
targetName = restored.name;
|
|
755
793
|
preservedIntent = restored.intent;
|
|
756
794
|
silent = true;
|
|
795
|
+
} else if (event.reason === "new" && previous?.pendingResetRole) {
|
|
796
|
+
targetName = previous.pendingResetRole.name;
|
|
797
|
+
} else if (event.reason === "new") {
|
|
798
|
+
targetName = pickNewSessionRoleName(
|
|
799
|
+
previous?.activeRole ?? null,
|
|
800
|
+
pi,
|
|
801
|
+
state.settings,
|
|
802
|
+
state.roles
|
|
803
|
+
);
|
|
757
804
|
} else {
|
|
758
|
-
targetName =
|
|
805
|
+
targetName = pickInitialRoleName(pi, state.settings, state.roles);
|
|
759
806
|
silent = event.reason === "startup";
|
|
760
807
|
}
|
|
761
808
|
state.intent = preservedIntent;
|
|
@@ -800,10 +847,14 @@ function index_default(pi) {
|
|
|
800
847
|
const wantsReset = tokens.includes("--reset");
|
|
801
848
|
const name = sub;
|
|
802
849
|
if (wantsReset) {
|
|
803
|
-
|
|
850
|
+
const request = { name, requestedAt: Date.now() };
|
|
851
|
+
state.pendingResetRequest = request;
|
|
852
|
+
pi.appendEntry(RESET_ROLE_REQUEST_ENTRY_TYPE, request);
|
|
804
853
|
const result = await resetSession(ctx);
|
|
805
854
|
if (result.cancelled) {
|
|
806
|
-
state.
|
|
855
|
+
state.pendingResetRequest = void 0;
|
|
856
|
+
discardProcessTransfer(ctx.sessionManager.getSessionFile());
|
|
857
|
+
pi.appendEntry(RESET_ROLE_CANCELLED_ENTRY_TYPE, { cancelledAt: Date.now() });
|
|
807
858
|
ctx.ui.notify(`Role switch to "${name}" cancelled.`, "info");
|
|
808
859
|
}
|
|
809
860
|
return;
|
|
@@ -843,14 +894,72 @@ function findRestoredState(ctx) {
|
|
|
843
894
|
} catch {
|
|
844
895
|
return void 0;
|
|
845
896
|
}
|
|
897
|
+
return findActiveRoleState(entries);
|
|
898
|
+
}
|
|
899
|
+
function pickPreviousSessionRoleState(diskState, processState) {
|
|
900
|
+
return hasPreviousRoleState(diskState) ? diskState : processState ?? diskState;
|
|
901
|
+
}
|
|
902
|
+
function hasPreviousRoleState(state) {
|
|
903
|
+
return !!state && (!!state.activeRole || !!state.pendingResetRole);
|
|
904
|
+
}
|
|
905
|
+
function activeRoleStateFromResolved(role, intent) {
|
|
906
|
+
return {
|
|
907
|
+
name: role.name,
|
|
908
|
+
source: role.source,
|
|
909
|
+
path: role.path,
|
|
910
|
+
intent,
|
|
911
|
+
appliedAt: Date.now()
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
function findPreviousSessionRoleState(previousSessionFile) {
|
|
915
|
+
if (!previousSessionFile) return void 0;
|
|
916
|
+
try {
|
|
917
|
+
return resolvePreviousSessionRoleState(SessionManager.open(previousSessionFile).getEntries());
|
|
918
|
+
} catch (err) {
|
|
919
|
+
debugLog("index", `could not read previous session ${previousSessionFile}`, String(err));
|
|
920
|
+
return void 0;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
function resolvePreviousSessionRoleState(entries) {
|
|
924
|
+
let pendingResetRole;
|
|
846
925
|
for (let i = entries.length - 1; i >= 0; i--) {
|
|
847
|
-
const
|
|
848
|
-
if (
|
|
849
|
-
|
|
926
|
+
const entry = entries[i];
|
|
927
|
+
if (!entry || entry.type !== "custom") continue;
|
|
928
|
+
if (entry.customType === RESET_ROLE_CANCELLED_ENTRY_TYPE) break;
|
|
929
|
+
if (entry.customType === RESET_ROLE_REQUEST_ENTRY_TYPE) {
|
|
930
|
+
const request = asResetRoleRequest(entry.data);
|
|
931
|
+
if (request) pendingResetRole = request;
|
|
932
|
+
break;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
return { activeRole: findActiveRoleState(entries), pendingResetRole };
|
|
936
|
+
}
|
|
937
|
+
function findActiveRoleState(entries) {
|
|
938
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
939
|
+
const entry = entries[i];
|
|
940
|
+
if (entry?.type === "custom" && entry.customType === ACTIVE_ROLE_ENTRY_TYPE) {
|
|
941
|
+
const state = asActiveRoleState(entry.data);
|
|
942
|
+
if (state) return state;
|
|
850
943
|
}
|
|
851
944
|
}
|
|
852
945
|
return void 0;
|
|
853
946
|
}
|
|
947
|
+
function asActiveRoleState(data) {
|
|
948
|
+
if (!data || typeof data !== "object") return void 0;
|
|
949
|
+
const candidate = data;
|
|
950
|
+
if (typeof candidate.name !== "string" || candidate.name.length === 0 || typeof candidate.source !== "string" || typeof candidate.path !== "string" || typeof candidate.appliedAt !== "number" || candidate.intent !== void 0 && typeof candidate.intent !== "string") {
|
|
951
|
+
return void 0;
|
|
952
|
+
}
|
|
953
|
+
return candidate;
|
|
954
|
+
}
|
|
955
|
+
function asResetRoleRequest(data) {
|
|
956
|
+
if (!data || typeof data !== "object") return void 0;
|
|
957
|
+
const candidate = data;
|
|
958
|
+
if (typeof candidate.name !== "string" || candidate.name.trim().length === 0 || typeof candidate.requestedAt !== "number") {
|
|
959
|
+
return void 0;
|
|
960
|
+
}
|
|
961
|
+
return { name: candidate.name, requestedAt: candidate.requestedAt };
|
|
962
|
+
}
|
|
854
963
|
async function applyResolved(pi, ctx, state, name, options) {
|
|
855
964
|
let resolved;
|
|
856
965
|
try {
|
|
@@ -951,7 +1060,10 @@ function subcommandDescription(sub) {
|
|
|
951
1060
|
export {
|
|
952
1061
|
composeSystemPrompt,
|
|
953
1062
|
index_default as default,
|
|
1063
|
+
findPreviousSessionRoleState,
|
|
954
1064
|
pickInitialRoleName,
|
|
955
1065
|
pickNewSessionRoleName,
|
|
1066
|
+
pickPreviousSessionRoleState,
|
|
1067
|
+
resolvePreviousSessionRoleState,
|
|
956
1068
|
roleCompletions
|
|
957
1069
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gkzhb/pi-roles",
|
|
3
|
-
"version": "0.2.4-beta.
|
|
3
|
+
"version": "0.2.4-beta.2",
|
|
4
4
|
"description": "Role-based session configuration for pi coding agent. Launch a session as a named role and hot-swap roles mid-session, with optional pi-intercom and pi-mcp-adapter integration.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|