@femtomc/mu-agent 26.3.2 → 26.3.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/README.md +1 -1
- package/dist/extensions/ui.d.ts.map +1 -1
- package/dist/extensions/ui.js +186 -3
- package/dist/operator.d.ts.map +1 -1
- package/dist/operator.js +54 -8
- package/package.json +32 -32
package/README.md
CHANGED
|
@@ -77,7 +77,7 @@ Current stack:
|
|
|
77
77
|
|
|
78
78
|
- `brandingExtension` — mu compact header/footer branding + default theme
|
|
79
79
|
- `eventLogExtension` — event tail + watch widget
|
|
80
|
-
- `uiExtension` — programmable `UiDoc` surface (`/mu ui ...`, `mu_ui`)
|
|
80
|
+
- `uiExtension` — programmable `UiDoc` surface (`/mu ui ...`, `mu_ui`) with session-resume persistence via `custom` entries (`mu-ui-state/v1`)
|
|
81
81
|
|
|
82
82
|
Default operator UI theme is `mu-gruvbox-dark`.
|
|
83
83
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/extensions/ui.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/extensions/ui.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,+BAA+B,CAAC;AA0qDpF,wBAAgB,WAAW,CAAC,EAAE,EAAE,YAAY,QA4P3C;AAED,eAAe,WAAW,CAAC"}
|
package/dist/extensions/ui.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { normalizeUiDocs, parseUiDoc, resolveUiStatusProfileName, uiStatusProfileWarnings, } from "@femtomc/mu-core";
|
|
1
|
+
import { normalizeUiDocs, parseUiDoc, resolveUiStatusProfileName, stableSerializeJson, uiStatusProfileWarnings, } from "@femtomc/mu-core";
|
|
2
2
|
import { matchesKey, truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
|
|
3
3
|
import { registerMuSubcommand } from "./mu-command-dispatcher.js";
|
|
4
4
|
const UI_DISPLAY_DOCS_MAX = 16;
|
|
@@ -6,6 +6,8 @@ const UI_PICKER_COMPONENTS_MAX = 8;
|
|
|
6
6
|
const UI_PICKER_LIST_ITEMS_MAX = 4;
|
|
7
7
|
const UI_PICKER_KEYVALUE_ROWS_MAX = 4;
|
|
8
8
|
const UI_SESSION_KEY_FALLBACK = "__mu_ui_active_session__";
|
|
9
|
+
const UI_STATE_CUSTOM_TYPE = "mu-ui-state/v1";
|
|
10
|
+
const UI_STATE_SCHEMA_VERSION = 1;
|
|
9
11
|
const UI_PROMPT_PREVIEW_MAX = 160;
|
|
10
12
|
const UI_INTERACT_SHORTCUT_PRIMARY = "ctrl+shift+u";
|
|
11
13
|
const UI_INTERACT_SHORTCUT_FALLBACK = "alt+u";
|
|
@@ -46,6 +48,7 @@ function createState() {
|
|
|
46
48
|
interactionDepth: 0,
|
|
47
49
|
lastStatusText: null,
|
|
48
50
|
lastWidgetSignature: null,
|
|
51
|
+
lastPersistSignature: null,
|
|
49
52
|
};
|
|
50
53
|
}
|
|
51
54
|
function pruneStaleStates(nowMs) {
|
|
@@ -389,6 +392,164 @@ function parseDocListInput(value) {
|
|
|
389
392
|
}
|
|
390
393
|
return { ok: true, docs: normalizeUiDocs(docs, { maxDocs: UI_DISPLAY_DOCS_MAX }) };
|
|
391
394
|
}
|
|
395
|
+
function normalizeStringArray(value) {
|
|
396
|
+
if (!Array.isArray(value)) {
|
|
397
|
+
return [];
|
|
398
|
+
}
|
|
399
|
+
const out = [];
|
|
400
|
+
const seen = new Set();
|
|
401
|
+
for (const entry of value) {
|
|
402
|
+
if (typeof entry !== "string") {
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
const trimmed = entry.trim();
|
|
406
|
+
if (!trimmed || seen.has(trimmed)) {
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
seen.add(trimmed);
|
|
410
|
+
out.push(trimmed);
|
|
411
|
+
}
|
|
412
|
+
return out;
|
|
413
|
+
}
|
|
414
|
+
function parsePersistedPendingPrompt(value) {
|
|
415
|
+
if (!isPlainObject(value)) {
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
418
|
+
const kind = value.kind === "action" || value.kind === "review" ? value.kind : null;
|
|
419
|
+
if (!kind) {
|
|
420
|
+
return null;
|
|
421
|
+
}
|
|
422
|
+
const uiIdRaw = typeof value.ui_id === "string" ? value.ui_id.trim() : "";
|
|
423
|
+
if (!uiIdRaw) {
|
|
424
|
+
return null;
|
|
425
|
+
}
|
|
426
|
+
const actionIdRaw = typeof value.action_id === "string" ? value.action_id.trim() : "";
|
|
427
|
+
if (kind === "review") {
|
|
428
|
+
return { kind, ui_id: uiIdRaw };
|
|
429
|
+
}
|
|
430
|
+
if (actionIdRaw) {
|
|
431
|
+
return { kind, ui_id: uiIdRaw, action_id: actionIdRaw };
|
|
432
|
+
}
|
|
433
|
+
return { kind, ui_id: uiIdRaw };
|
|
434
|
+
}
|
|
435
|
+
function parsePersistedUiState(value) {
|
|
436
|
+
if (!isPlainObject(value)) {
|
|
437
|
+
return null;
|
|
438
|
+
}
|
|
439
|
+
if (value.v !== UI_STATE_SCHEMA_VERSION) {
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
442
|
+
const parsedDocs = parseDocListInput(value.docs);
|
|
443
|
+
if (!parsedDocs.ok) {
|
|
444
|
+
return null;
|
|
445
|
+
}
|
|
446
|
+
const pendingPrompts = [];
|
|
447
|
+
const pendingRaw = Array.isArray(value.pending_prompts) ? value.pending_prompts : [];
|
|
448
|
+
for (const pending of pendingRaw) {
|
|
449
|
+
const parsed = parsePersistedPendingPrompt(pending);
|
|
450
|
+
if (parsed) {
|
|
451
|
+
pendingPrompts.push(parsed);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
return {
|
|
455
|
+
v: 1,
|
|
456
|
+
docs: parsedDocs.docs,
|
|
457
|
+
pending_prompts: pendingPrompts,
|
|
458
|
+
prompted_revision_keys: normalizeStringArray(value.prompted_revision_keys),
|
|
459
|
+
awaiting_ui_ids: normalizeStringArray(value.awaiting_ui_ids),
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
function serializeUiState(state) {
|
|
463
|
+
retainPromptedRevisionKeysForActiveDocs(state);
|
|
464
|
+
retainAwaitingUiIdsForActiveDocs(state);
|
|
465
|
+
retainPendingPromptsForActiveDocs(state);
|
|
466
|
+
const docs = activeDocs(state, UI_DISPLAY_DOCS_MAX);
|
|
467
|
+
return {
|
|
468
|
+
v: 1,
|
|
469
|
+
docs,
|
|
470
|
+
pending_prompts: state.pendingPrompts.map((pending) => ({
|
|
471
|
+
kind: pending.kind,
|
|
472
|
+
ui_id: pending.uiId,
|
|
473
|
+
...(pending.actionId ? { action_id: pending.actionId } : {}),
|
|
474
|
+
})),
|
|
475
|
+
prompted_revision_keys: [...state.promptedRevisionKeys].sort((left, right) => left.localeCompare(right)),
|
|
476
|
+
awaiting_ui_ids: [...state.awaitingUiIds].sort((left, right) => left.localeCompare(right)),
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
function uiStatePersistSignature(value) {
|
|
480
|
+
return stableSerializeJson(value);
|
|
481
|
+
}
|
|
482
|
+
function persistUiStateSnapshot(pi, state) {
|
|
483
|
+
const snapshot = serializeUiState(state);
|
|
484
|
+
const signature = uiStatePersistSignature(snapshot);
|
|
485
|
+
if (state.lastPersistSignature === signature) {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
pi.appendEntry(UI_STATE_CUSTOM_TYPE, snapshot);
|
|
489
|
+
state.lastPersistSignature = signature;
|
|
490
|
+
}
|
|
491
|
+
function applyPersistedUiState(state, persisted) {
|
|
492
|
+
state.docsById.clear();
|
|
493
|
+
state.pendingPrompts = [];
|
|
494
|
+
state.promptedRevisionKeys.clear();
|
|
495
|
+
state.awaitingUiIds.clear();
|
|
496
|
+
state.interactionDepth = 0;
|
|
497
|
+
state.lastStatusText = null;
|
|
498
|
+
state.lastWidgetSignature = null;
|
|
499
|
+
for (const doc of persisted.docs) {
|
|
500
|
+
state.docsById.set(doc.ui_id, doc);
|
|
501
|
+
}
|
|
502
|
+
for (const revisionKey of persisted.prompted_revision_keys) {
|
|
503
|
+
state.promptedRevisionKeys.add(revisionKey);
|
|
504
|
+
}
|
|
505
|
+
for (const uiId of persisted.awaiting_ui_ids) {
|
|
506
|
+
state.awaitingUiIds.add(uiId);
|
|
507
|
+
}
|
|
508
|
+
for (const pending of persisted.pending_prompts) {
|
|
509
|
+
enqueuePendingPrompt(state, {
|
|
510
|
+
kind: pending.kind,
|
|
511
|
+
uiId: pending.ui_id,
|
|
512
|
+
actionId: pending.action_id,
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
retainPromptedRevisionKeysForActiveDocs(state);
|
|
516
|
+
retainAwaitingUiIdsForActiveDocs(state);
|
|
517
|
+
retainPendingPromptsForActiveDocs(state);
|
|
518
|
+
state.lastPersistSignature = uiStatePersistSignature(serializeUiState(state));
|
|
519
|
+
}
|
|
520
|
+
function latestPersistedUiStateFromBranch(entries) {
|
|
521
|
+
let latest = null;
|
|
522
|
+
for (const entry of entries) {
|
|
523
|
+
if (!isPlainObject(entry)) {
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
if (entry.type !== "custom" || entry.customType !== UI_STATE_CUSTOM_TYPE) {
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
const parsed = parsePersistedUiState(entry.data);
|
|
530
|
+
if (!parsed) {
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
533
|
+
latest = parsed;
|
|
534
|
+
}
|
|
535
|
+
return latest;
|
|
536
|
+
}
|
|
537
|
+
function restoreStateFromSessionBranch(ctx, key) {
|
|
538
|
+
const manager = ctx.sessionManager;
|
|
539
|
+
const branch = typeof manager.getBranch === "function" ? manager.getBranch() : [];
|
|
540
|
+
const restored = createState();
|
|
541
|
+
const persisted = latestPersistedUiStateFromBranch(branch);
|
|
542
|
+
if (persisted) {
|
|
543
|
+
applyPersistedUiState(restored, persisted);
|
|
544
|
+
}
|
|
545
|
+
const nowMs = Date.now();
|
|
546
|
+
pruneStaleStates(nowMs);
|
|
547
|
+
STATE_BY_SESSION.set(key, {
|
|
548
|
+
state: restored,
|
|
549
|
+
lastAccessMs: nowMs,
|
|
550
|
+
});
|
|
551
|
+
return restored;
|
|
552
|
+
}
|
|
392
553
|
function statusProfileWarningsExtraForDoc(doc) {
|
|
393
554
|
const warnings = uiStatusProfileWarnings(doc);
|
|
394
555
|
if (warnings.length === 0) {
|
|
@@ -1355,6 +1516,7 @@ export function uiExtension(pi) {
|
|
|
1355
1516
|
removePendingPromptsForUiId(state, selectedDoc.ui_id);
|
|
1356
1517
|
retainAwaitingUiIdsForActiveDocs(state);
|
|
1357
1518
|
retainPendingPromptsForActiveDocs(state);
|
|
1519
|
+
persistUiStateSnapshot(pi, state);
|
|
1358
1520
|
ctx.ui.notify(`Submitted prompt from ${selectedDoc.ui_id}/${selectedAction.id}.`, "info");
|
|
1359
1521
|
});
|
|
1360
1522
|
registerMuSubcommand(pi, {
|
|
@@ -1432,15 +1594,35 @@ export function uiExtension(pi) {
|
|
|
1432
1594
|
if (ctx.hasUI && result.ok && result.changedUiIds && result.changedUiIds.length > 0) {
|
|
1433
1595
|
armAutoPromptForUiDocs(state, result.changedUiIds);
|
|
1434
1596
|
}
|
|
1597
|
+
const shouldPersistMutation = result.ok &&
|
|
1598
|
+
(result.action === "set" ||
|
|
1599
|
+
result.action === "update" ||
|
|
1600
|
+
result.action === "replace" ||
|
|
1601
|
+
result.action === "remove" ||
|
|
1602
|
+
result.action === "clear");
|
|
1603
|
+
if (shouldPersistMutation) {
|
|
1604
|
+
persistUiStateSnapshot(pi, state);
|
|
1605
|
+
}
|
|
1435
1606
|
refreshUi(ctx);
|
|
1436
1607
|
return buildToolResult({ state, ...result });
|
|
1437
1608
|
},
|
|
1438
1609
|
});
|
|
1439
|
-
|
|
1610
|
+
const restoreAndRefresh = (ctx) => {
|
|
1611
|
+
const key = sessionKey(ctx);
|
|
1612
|
+
restoreStateFromSessionBranch(ctx, key);
|
|
1440
1613
|
refreshUi(ctx);
|
|
1614
|
+
};
|
|
1615
|
+
pi.on("session_start", (_event, ctx) => {
|
|
1616
|
+
restoreAndRefresh(ctx);
|
|
1441
1617
|
});
|
|
1442
1618
|
pi.on("session_switch", (_event, ctx) => {
|
|
1443
|
-
|
|
1619
|
+
restoreAndRefresh(ctx);
|
|
1620
|
+
});
|
|
1621
|
+
pi.on("session_fork", (_event, ctx) => {
|
|
1622
|
+
restoreAndRefresh(ctx);
|
|
1623
|
+
});
|
|
1624
|
+
pi.on("session_tree", (_event, ctx) => {
|
|
1625
|
+
restoreAndRefresh(ctx);
|
|
1444
1626
|
});
|
|
1445
1627
|
pi.on("agent_end", async (_event, ctx) => {
|
|
1446
1628
|
if (!ctx.hasUI) {
|
|
@@ -1453,6 +1635,7 @@ export function uiExtension(pi) {
|
|
|
1453
1635
|
if (!pending) {
|
|
1454
1636
|
return;
|
|
1455
1637
|
}
|
|
1638
|
+
persistUiStateSnapshot(pi, state);
|
|
1456
1639
|
if (pending.kind === "action") {
|
|
1457
1640
|
ctx.ui.notify(`Agent requested input via ${pending.uiId}. Submit now or press ${UI_INTERACT_SHORTCUT_HINT} later.`, "info");
|
|
1458
1641
|
}
|
package/dist/operator.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operator.d.ts","sourceRoot":"","sources":["../src/operator.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"operator.d.ts","sourceRoot":"","sources":["../src/operator.ts"],"names":[],"mappings":"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"}
|
package/dist/operator.js
CHANGED
|
@@ -173,16 +173,43 @@ function defaultSessionId() {
|
|
|
173
173
|
function defaultTurnId() {
|
|
174
174
|
return `turn-${crypto.randomUUID()}`;
|
|
175
175
|
}
|
|
176
|
+
function classifyProviderFailureCodeFromMessage(message) {
|
|
177
|
+
if (!message) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
const normalized = message.trim().toLowerCase();
|
|
181
|
+
if (!normalized) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
if (normalized.includes("chatgpt usage limit") ||
|
|
185
|
+
normalized.includes("usage limit") ||
|
|
186
|
+
normalized.includes("insufficient_quota") ||
|
|
187
|
+
normalized.includes("quota exceeded") ||
|
|
188
|
+
normalized.includes("billing hard limit")) {
|
|
189
|
+
return "operator_provider_usage_limit";
|
|
190
|
+
}
|
|
191
|
+
if (normalized.includes("context_length_exceeded") ||
|
|
192
|
+
normalized.includes("context window") ||
|
|
193
|
+
normalized.includes("maximum context length") ||
|
|
194
|
+
normalized.includes("input exceeds the context window")) {
|
|
195
|
+
return "operator_provider_context_length_exceeded";
|
|
196
|
+
}
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
176
199
|
function buildOperatorFailureFallbackMessage(code) {
|
|
177
200
|
const reasonLine = code === "operator_timeout"
|
|
178
201
|
? "The operator turn exceeded the messaging timeout before a safe response was produced."
|
|
179
202
|
: code === "operator_busy"
|
|
180
203
|
? "Another operator turn is already in progress for this conversation."
|
|
181
|
-
: code === "
|
|
182
|
-
? "The operator
|
|
183
|
-
: code === "
|
|
184
|
-
? "The operator turn
|
|
185
|
-
:
|
|
204
|
+
: code === "operator_provider_usage_limit"
|
|
205
|
+
? "The configured operator provider rejected the turn due to usage or quota limits."
|
|
206
|
+
: code === "operator_provider_context_length_exceeded"
|
|
207
|
+
? "The configured operator provider rejected the turn because the context window was exceeded."
|
|
208
|
+
: code === "operator_empty_response"
|
|
209
|
+
? "The operator completed without a usable response payload."
|
|
210
|
+
: code === "operator_cancelled"
|
|
211
|
+
? "The operator turn was cancelled before completion."
|
|
212
|
+
: "An internal operator runtime/formatting error interrupted the turn.";
|
|
186
213
|
return [
|
|
187
214
|
"I could not complete that turn safely.",
|
|
188
215
|
`Code: ${code}`,
|
|
@@ -198,6 +225,16 @@ function classifyBackendFailureCode(err) {
|
|
|
198
225
|
if (message.includes("pi operator timeout") || message.includes("operator timeout")) {
|
|
199
226
|
return "operator_timeout";
|
|
200
227
|
}
|
|
228
|
+
if (message.includes("operator_provider_usage_limit")) {
|
|
229
|
+
return "operator_provider_usage_limit";
|
|
230
|
+
}
|
|
231
|
+
if (message.includes("operator_provider_context_length_exceeded")) {
|
|
232
|
+
return "operator_provider_context_length_exceeded";
|
|
233
|
+
}
|
|
234
|
+
const providerFailureCode = classifyProviderFailureCodeFromMessage(message);
|
|
235
|
+
if (providerFailureCode) {
|
|
236
|
+
return providerFailureCode;
|
|
237
|
+
}
|
|
201
238
|
if (message.includes("operator_empty_response")) {
|
|
202
239
|
return "operator_empty_response";
|
|
203
240
|
}
|
|
@@ -914,6 +951,8 @@ export class PiMessagingOperatorBackend {
|
|
|
914
951
|
const sessionRecord = await this.#resolveSession(input.sessionId, input.inbound.repo_root, overrides);
|
|
915
952
|
const session = sessionRecord.session;
|
|
916
953
|
let assistantText = "";
|
|
954
|
+
let assistantStopReason = null;
|
|
955
|
+
let assistantErrorMessage = null;
|
|
917
956
|
let capturedCommand = null;
|
|
918
957
|
let capturedUiDocs = [];
|
|
919
958
|
const turnEnv = autonomousTurnEnvironment(input.inbound.metadata);
|
|
@@ -927,6 +966,8 @@ export class PiMessagingOperatorBackend {
|
|
|
927
966
|
// Capture assistant text for fallback responses.
|
|
928
967
|
if (event?.type === "message_end" && event?.message?.role === "assistant") {
|
|
929
968
|
const msg = event.message;
|
|
969
|
+
assistantStopReason = typeof msg.stopReason === "string" ? msg.stopReason.trim().toLowerCase() : null;
|
|
970
|
+
assistantErrorMessage = typeof msg.errorMessage === "string" ? msg.errorMessage.trim() : null;
|
|
930
971
|
if (typeof msg.text === "string") {
|
|
931
972
|
assistantText = msg.text;
|
|
932
973
|
}
|
|
@@ -993,6 +1034,8 @@ export class PiMessagingOperatorBackend {
|
|
|
993
1034
|
}
|
|
994
1035
|
await session.agent.waitForIdle();
|
|
995
1036
|
assistantText = "";
|
|
1037
|
+
assistantStopReason = null;
|
|
1038
|
+
assistantErrorMessage = null;
|
|
996
1039
|
capturedCommand = null;
|
|
997
1040
|
await promptOnce();
|
|
998
1041
|
}
|
|
@@ -1001,7 +1044,7 @@ export class PiMessagingOperatorBackend {
|
|
|
1001
1044
|
await this.#auditTurn(input, {
|
|
1002
1045
|
outcome: "error",
|
|
1003
1046
|
reason: err instanceof Error ? err.message : "operator_backend_error",
|
|
1004
|
-
messagePreview: assistantText,
|
|
1047
|
+
messagePreview: assistantText || assistantErrorMessage || undefined,
|
|
1005
1048
|
});
|
|
1006
1049
|
throw err;
|
|
1007
1050
|
}
|
|
@@ -1027,11 +1070,14 @@ export class PiMessagingOperatorBackend {
|
|
|
1027
1070
|
// Otherwise treat the assistant text as a plain response.
|
|
1028
1071
|
const message = assistantText.trim();
|
|
1029
1072
|
if (!message) {
|
|
1073
|
+
const providerFailureCode = classifyProviderFailureCodeFromMessage(assistantErrorMessage);
|
|
1074
|
+
const emptyResponseCode = providerFailureCode ?? (assistantStopReason === "aborted" ? "operator_cancelled" : null) ?? "operator_empty_response";
|
|
1030
1075
|
await this.#auditTurn(input, {
|
|
1031
1076
|
outcome: "error",
|
|
1032
|
-
reason:
|
|
1077
|
+
reason: emptyResponseCode,
|
|
1078
|
+
messagePreview: assistantErrorMessage || undefined,
|
|
1033
1079
|
});
|
|
1034
|
-
throw new Error(
|
|
1080
|
+
throw new Error(emptyResponseCode);
|
|
1035
1081
|
}
|
|
1036
1082
|
const responseMessage = message.slice(0, OPERATOR_RESPONSE_MAX_CHARS);
|
|
1037
1083
|
await this.#auditTurn(input, {
|
package/package.json
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
|
|
2
|
+
"name": "@femtomc/mu-agent",
|
|
3
|
+
"version": "26.3.4",
|
|
4
|
+
"description": "Shared operator runtime for mu assistant sessions and serve extensions.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mu",
|
|
7
|
+
"agent",
|
|
8
|
+
"runtime",
|
|
9
|
+
"chat",
|
|
10
|
+
"extensions"
|
|
11
|
+
],
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist/**",
|
|
23
|
+
"prompts/**",
|
|
24
|
+
"themes/**"
|
|
25
|
+
],
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@femtomc/mu-core": "26.3.4",
|
|
28
|
+
"@mariozechner/pi-agent-core": "^0.54.2",
|
|
29
|
+
"@mariozechner/pi-ai": "^0.54.2",
|
|
30
|
+
"@mariozechner/pi-coding-agent": "^0.54.2",
|
|
31
|
+
"@mariozechner/pi-tui": "^0.54.2",
|
|
32
|
+
"zod": "^4.1.9"
|
|
33
|
+
}
|
|
34
34
|
}
|