@femtomc/mu-agent 26.3.1 → 26.3.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/dist/operator.d.ts.map +1 -1
- package/dist/operator.js +142 -20
- package/package.json +32 -32
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":"AAAA,OAAO,EAAe,KAAK,KAAK,EAAmB,MAAM,kBAAkB,CAAC;AAI5E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAmB,KAAK,mBAAmB,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjG,OAAO,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AAEtE,MAAM,MAAM,gCAAgC,GAAG;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,uBAAuB,EAAE,MAAM,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,KAAK,eAAe,GAAG,gCAAgC,CAAC;AACxD,KAAK,eAAe,GAAG,gCAAgC,CAAC;AAQxD,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAgCxC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAIpF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAW1C,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAExF,MAAM,MAAM,wBAAwB,GAAG;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACxC,OAAO,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC7E,YAAY,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAC7D,OAAO,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC;AAED,MAAM,MAAM,gBAAgB,GACzB;IACA,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;CACtB,GACD;IACA,IAAI,EAAE,SAAS,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;CACtB,GACD;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EACH,mBAAmB,GACnB,4BAA4B,GAC5B,yBAAyB,GACzB,oBAAoB,GACpB,iBAAiB,GACjB,mBAAmB,GACnB,sBAAsB,GACtB,uBAAuB,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;CACtB,CAAC;AAEL,MAAM,MAAM,yBAAyB,GAAG;IACvC,eAAe,CAAC,EAAE,sBAAsB,CAAC;CACzC,CAAC;AAMF,qBAAa,qBAAqB;;gBAGd,IAAI,GAAE,yBAA8B;IAIhD,OAAO,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,uBAAuB,CAAC;QAAC,OAAO,EAAE,eAAe,CAAA;KAAE,GACjF;QACA,IAAI,EAAE,UAAU,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;KACnB,GACD;QACA,IAAI,EAAE,QAAQ,CAAC;QACf,MAAM,EACH,4BAA4B,GAC5B,iBAAiB,GACjB,mBAAmB,GACnB,sBAAsB,GACtB,uBAAuB,CAAC;QAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;KAChB;CAyGJ;AAED,MAAM,MAAM,yCAAyC,GAAG;IACvD,YAAY,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC;IAClF,YAAY,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACnF,IAAI,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IAC1C,OAAO,EAAE,wBAAwB,CAAC;IAClC,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,gBAAgB,CAAC,EAAE,MAAM,MAAM,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,MAAM,CAAC;IAC7B,wBAAwB,CAAC,EAAE,yCAAyC,CAAC;CACrE,CAAC;AAwRF,qBAAa,gCAAiC,YAAW,yCAAyC;;gBAM9E,IAAI,EAAE,MAAM;IAuDlB,YAAY,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAK7D,YAAY,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUvE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAGlC;AAED,qBAAa,wBAAwB;;gBAWjB,IAAI,EAAE,4BAA4B;IAgExC,aAAa,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,eAAe,CAAC;QAAC,OAAO,EAAE,eAAe,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAmHtG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAMlC;AAED,MAAM,MAAM,8BAA8B,GAAG;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACnE,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,qBAAqB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;CACrD,CAAC;AAEF,OAAO,EAAE,8BAA8B,EAAE,CAAC;AAgG1C,qBAAa,0BAA2B,YAAW,wBAAwB;;gBAkBvD,IAAI,GAAE,8BAAmC;IAgO/C,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqBjD,OAAO,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAmJlF,OAAO,IAAI,IAAI;CAKtB"}
|
package/dist/operator.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { UiDocSchema, normalizeUiDocs } from "@femtomc/mu-core";
|
|
2
2
|
import { appendJsonl, getStorePaths } from "@femtomc/mu-core/node";
|
|
3
3
|
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
4
|
-
import { dirname, join } from "node:path";
|
|
4
|
+
import { dirname, isAbsolute, join } from "node:path";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { CommandContextResolver } from "./command_context.js";
|
|
7
7
|
import { createMuSession } from "./session_factory.js";
|
|
@@ -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
|
}
|
|
@@ -255,6 +292,13 @@ function nonEmptyString(value) {
|
|
|
255
292
|
const trimmed = value.trim();
|
|
256
293
|
return trimmed.length > 0 ? trimmed : null;
|
|
257
294
|
}
|
|
295
|
+
function autonomousSessionIdOverride(metadata) {
|
|
296
|
+
const source = nonEmptyString(metadata.source);
|
|
297
|
+
if (source !== "autonomous_ingress") {
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
return nonEmptyString(metadata.operator_session_id);
|
|
301
|
+
}
|
|
258
302
|
function autonomousTurnEnvironment(metadata) {
|
|
259
303
|
const source = nonEmptyString(metadata.source);
|
|
260
304
|
if (source !== "autonomous_ingress") {
|
|
@@ -281,6 +325,38 @@ function autonomousTurnEnvironment(metadata) {
|
|
|
281
325
|
}
|
|
282
326
|
return out;
|
|
283
327
|
}
|
|
328
|
+
function resolveRepoPath(repoRoot, candidate) {
|
|
329
|
+
return isAbsolute(candidate) ? candidate : join(repoRoot, candidate);
|
|
330
|
+
}
|
|
331
|
+
function autonomousOperatorSessionOverrides(metadata, repoRoot) {
|
|
332
|
+
const source = nonEmptyString(metadata.source);
|
|
333
|
+
if (source !== "autonomous_ingress") {
|
|
334
|
+
return {};
|
|
335
|
+
}
|
|
336
|
+
const provider = nonEmptyString(metadata.operator_provider);
|
|
337
|
+
const model = nonEmptyString(metadata.operator_model);
|
|
338
|
+
const thinking = nonEmptyString(metadata.operator_thinking);
|
|
339
|
+
const sessionFileRaw = nonEmptyString(metadata.operator_session_file);
|
|
340
|
+
const sessionDirRaw = nonEmptyString(metadata.operator_session_dir);
|
|
341
|
+
const sessionFile = sessionFileRaw ? resolveRepoPath(repoRoot, sessionFileRaw) : undefined;
|
|
342
|
+
const sessionDir = sessionDirRaw ? resolveRepoPath(repoRoot, sessionDirRaw) : undefined;
|
|
343
|
+
return {
|
|
344
|
+
...(provider ? { provider } : {}),
|
|
345
|
+
...(model ? { model } : {}),
|
|
346
|
+
...(thinking ? { thinking } : {}),
|
|
347
|
+
...(sessionFile ? { sessionFile } : {}),
|
|
348
|
+
...(sessionDir ? { sessionDir } : {}),
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
function operatorSessionProfileKey(opts) {
|
|
352
|
+
return JSON.stringify({
|
|
353
|
+
provider: opts.provider ?? null,
|
|
354
|
+
model: opts.model ?? null,
|
|
355
|
+
thinking: opts.thinking ?? null,
|
|
356
|
+
sessionFile: opts.sessionFile ?? null,
|
|
357
|
+
sessionDir: opts.sessionDir ?? null,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
284
360
|
function isUiToolName(toolName) {
|
|
285
361
|
const normalized = toolName.trim().toLowerCase();
|
|
286
362
|
return normalized === "mu_ui";
|
|
@@ -411,6 +487,10 @@ export class MessagingOperatorRuntime {
|
|
|
411
487
|
this.#conversationSessionStore = opts.conversationSessionStore ?? null;
|
|
412
488
|
}
|
|
413
489
|
async #resolveSessionId(inbound, binding) {
|
|
490
|
+
const explicitSessionId = autonomousSessionIdOverride(inbound.metadata);
|
|
491
|
+
if (explicitSessionId) {
|
|
492
|
+
return explicitSessionId;
|
|
493
|
+
}
|
|
414
494
|
const key = conversationKey(inbound, binding);
|
|
415
495
|
const existing = this.#sessionByConversation.get(key);
|
|
416
496
|
if (existing) {
|
|
@@ -717,10 +797,24 @@ export class PiMessagingOperatorBackend {
|
|
|
717
797
|
}
|
|
718
798
|
this.#activePromptCountsBySession.set(sessionId, current - 1);
|
|
719
799
|
}
|
|
720
|
-
#sessionPersistence(repoRoot, sessionId) {
|
|
800
|
+
#sessionPersistence(repoRoot, sessionId, overrides) {
|
|
721
801
|
if (!this.#persistSessions) {
|
|
722
802
|
return undefined;
|
|
723
803
|
}
|
|
804
|
+
if (overrides.sessionFile) {
|
|
805
|
+
return {
|
|
806
|
+
mode: "open",
|
|
807
|
+
sessionDir: overrides.sessionDir,
|
|
808
|
+
sessionFile: overrides.sessionFile,
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
if (overrides.sessionDir) {
|
|
812
|
+
return {
|
|
813
|
+
mode: "open",
|
|
814
|
+
sessionDir: overrides.sessionDir,
|
|
815
|
+
sessionFile: join(overrides.sessionDir, `${sessionFileStem(sessionId)}.jsonl`),
|
|
816
|
+
};
|
|
817
|
+
}
|
|
724
818
|
const sessionDir = this.#sessionDirForRepoRoot(repoRoot);
|
|
725
819
|
const sessionFile = join(sessionDir, `${sessionFileStem(sessionId)}.jsonl`);
|
|
726
820
|
return {
|
|
@@ -729,15 +823,25 @@ export class PiMessagingOperatorBackend {
|
|
|
729
823
|
sessionFile,
|
|
730
824
|
};
|
|
731
825
|
}
|
|
732
|
-
async #createSession(repoRoot, sessionId, nowMs) {
|
|
826
|
+
async #createSession(repoRoot, sessionId, nowMs, overrides) {
|
|
827
|
+
const provider = overrides.provider ?? this.#provider;
|
|
828
|
+
const model = overrides.model ?? this.#model;
|
|
829
|
+
const thinking = overrides.thinking ?? this.#thinking;
|
|
830
|
+
const profileKey = operatorSessionProfileKey({
|
|
831
|
+
provider,
|
|
832
|
+
model,
|
|
833
|
+
thinking,
|
|
834
|
+
sessionFile: overrides.sessionFile,
|
|
835
|
+
sessionDir: overrides.sessionDir,
|
|
836
|
+
});
|
|
733
837
|
const session = await this.#sessionFactory({
|
|
734
838
|
cwd: repoRoot,
|
|
735
839
|
systemPrompt: this.#systemPrompt,
|
|
736
|
-
provider
|
|
737
|
-
model
|
|
738
|
-
thinking
|
|
840
|
+
provider,
|
|
841
|
+
model,
|
|
842
|
+
thinking,
|
|
739
843
|
extensionPaths: this.#extensionPaths,
|
|
740
|
-
session: this.#sessionPersistence(repoRoot, sessionId),
|
|
844
|
+
session: this.#sessionPersistence(repoRoot, sessionId, overrides),
|
|
741
845
|
bashToolOptions: {
|
|
742
846
|
spawnHook: (context) => {
|
|
743
847
|
const turnEnv = this.#autonomousTurnEnvBySession.get(sessionId);
|
|
@@ -770,20 +874,28 @@ export class PiMessagingOperatorBackend {
|
|
|
770
874
|
repoRoot,
|
|
771
875
|
createdAtMs: nowMs,
|
|
772
876
|
lastUsedAtMs: nowMs,
|
|
877
|
+
profileKey,
|
|
773
878
|
};
|
|
774
879
|
}
|
|
775
|
-
async #resolveSession(sessionId, repoRoot) {
|
|
880
|
+
async #resolveSession(sessionId, repoRoot, overrides) {
|
|
776
881
|
const nowMs = Math.trunc(this.#nowMs());
|
|
777
882
|
this.#pruneSessions(nowMs);
|
|
883
|
+
const requestedProfileKey = operatorSessionProfileKey({
|
|
884
|
+
provider: overrides.provider ?? this.#provider,
|
|
885
|
+
model: overrides.model ?? this.#model,
|
|
886
|
+
thinking: overrides.thinking ?? this.#thinking,
|
|
887
|
+
sessionFile: overrides.sessionFile,
|
|
888
|
+
sessionDir: overrides.sessionDir,
|
|
889
|
+
});
|
|
778
890
|
const existing = this.#sessions.get(sessionId);
|
|
779
|
-
if (existing && existing.repoRoot === repoRoot) {
|
|
891
|
+
if (existing && existing.repoRoot === repoRoot && existing.profileKey === requestedProfileKey) {
|
|
780
892
|
existing.lastUsedAtMs = nowMs;
|
|
781
893
|
return existing;
|
|
782
894
|
}
|
|
783
|
-
if (existing
|
|
895
|
+
if (existing) {
|
|
784
896
|
this.#disposeSession(sessionId);
|
|
785
897
|
}
|
|
786
|
-
const created = await this.#createSession(repoRoot, sessionId, nowMs);
|
|
898
|
+
const created = await this.#createSession(repoRoot, sessionId, nowMs, overrides);
|
|
787
899
|
this.#sessions.set(sessionId, created);
|
|
788
900
|
this.#pruneSessions(nowMs);
|
|
789
901
|
return created;
|
|
@@ -835,9 +947,12 @@ export class PiMessagingOperatorBackend {
|
|
|
835
947
|
}
|
|
836
948
|
}
|
|
837
949
|
async runTurn(input) {
|
|
838
|
-
const
|
|
950
|
+
const overrides = autonomousOperatorSessionOverrides(input.inbound.metadata, input.inbound.repo_root);
|
|
951
|
+
const sessionRecord = await this.#resolveSession(input.sessionId, input.inbound.repo_root, overrides);
|
|
839
952
|
const session = sessionRecord.session;
|
|
840
953
|
let assistantText = "";
|
|
954
|
+
let assistantStopReason = null;
|
|
955
|
+
let assistantErrorMessage = null;
|
|
841
956
|
let capturedCommand = null;
|
|
842
957
|
let capturedUiDocs = [];
|
|
843
958
|
const turnEnv = autonomousTurnEnvironment(input.inbound.metadata);
|
|
@@ -851,6 +966,8 @@ export class PiMessagingOperatorBackend {
|
|
|
851
966
|
// Capture assistant text for fallback responses.
|
|
852
967
|
if (event?.type === "message_end" && event?.message?.role === "assistant") {
|
|
853
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;
|
|
854
971
|
if (typeof msg.text === "string") {
|
|
855
972
|
assistantText = msg.text;
|
|
856
973
|
}
|
|
@@ -917,6 +1034,8 @@ export class PiMessagingOperatorBackend {
|
|
|
917
1034
|
}
|
|
918
1035
|
await session.agent.waitForIdle();
|
|
919
1036
|
assistantText = "";
|
|
1037
|
+
assistantStopReason = null;
|
|
1038
|
+
assistantErrorMessage = null;
|
|
920
1039
|
capturedCommand = null;
|
|
921
1040
|
await promptOnce();
|
|
922
1041
|
}
|
|
@@ -925,7 +1044,7 @@ export class PiMessagingOperatorBackend {
|
|
|
925
1044
|
await this.#auditTurn(input, {
|
|
926
1045
|
outcome: "error",
|
|
927
1046
|
reason: err instanceof Error ? err.message : "operator_backend_error",
|
|
928
|
-
messagePreview: assistantText,
|
|
1047
|
+
messagePreview: assistantText || assistantErrorMessage || undefined,
|
|
929
1048
|
});
|
|
930
1049
|
throw err;
|
|
931
1050
|
}
|
|
@@ -951,11 +1070,14 @@ export class PiMessagingOperatorBackend {
|
|
|
951
1070
|
// Otherwise treat the assistant text as a plain response.
|
|
952
1071
|
const message = assistantText.trim();
|
|
953
1072
|
if (!message) {
|
|
1073
|
+
const providerFailureCode = classifyProviderFailureCodeFromMessage(assistantErrorMessage);
|
|
1074
|
+
const emptyResponseCode = providerFailureCode ?? (assistantStopReason === "aborted" ? "operator_cancelled" : null) ?? "operator_empty_response";
|
|
954
1075
|
await this.#auditTurn(input, {
|
|
955
1076
|
outcome: "error",
|
|
956
|
-
reason:
|
|
1077
|
+
reason: emptyResponseCode,
|
|
1078
|
+
messagePreview: assistantErrorMessage || undefined,
|
|
957
1079
|
});
|
|
958
|
-
throw new Error(
|
|
1080
|
+
throw new Error(emptyResponseCode);
|
|
959
1081
|
}
|
|
960
1082
|
const responseMessage = message.slice(0, OPERATOR_RESPONSE_MAX_CHARS);
|
|
961
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.3",
|
|
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.3",
|
|
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
|
}
|