mixdog 1.2.6 → 1.3.0
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/LICENSES/simple-icons-CC0-1.0.txt +30 -0
- package/NOTICE.md +19 -0
- package/package.json +4 -1
- package/scripts/check-model-recommendations.mjs +89 -0
- package/scripts/gate-local.mjs +7 -0
- package/scripts/lib/isolated-test-env.mjs +16 -0
- package/src/agents/reviewer/AGENT.md +4 -2
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +7 -0
- package/src/defaults/skills/browser-use/SKILL.md +5 -0
- package/src/defaults/skills/memory-management/SKILL.md +4 -1
- package/src/defaults/skills/setup/references/actions.md +11 -4
- package/src/defaults/skills/setup-guide/SKILL.md +175 -0
- package/src/defaults/skills/setup-guide/model-recommendations.json +333 -0
- package/src/lib/rules-builder.cjs +55 -6
- package/src/rules/agent/AGENT.md +4 -0
- package/src/rules/agent-mode/AGENT_MODE.md +24 -0
- package/src/rules/agent-mode/MIXY.md +21 -0
- package/src/rules/agent-mode/ROUTINE.md +6 -0
- package/src/rules/lead/LEAD.md +7 -3
- package/src/rules/shared/70-delivery.md +3 -0
- package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +86 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +77 -14
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +182 -13
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +4 -2
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +215 -0
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -4
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +10 -1
- package/src/runtime/agent/orchestrator/mcp/client.mjs +115 -11
- package/src/runtime/agent/orchestrator/mcp/oauth-account.mjs +97 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +49 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +59 -9
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +32 -7
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +45 -6
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +195 -6
- package/src/runtime/agent/orchestrator/mcp/server-connectors.mjs +17 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +10 -3
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +17 -12
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +96 -1
- package/src/runtime/agent/orchestrator/runtime-core/context-status-shape.mjs +4 -0
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +6 -4
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +12 -0
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +12 -6
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +32 -5
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +10 -4
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +50 -20
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/agent-home.d.mts +4 -0
- package/src/runtime/agent/orchestrator/session/agent-home.mjs +33 -0
- package/src/runtime/agent/orchestrator/session/agent-mode.mjs +62 -0
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +31 -0
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +241 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +162 -0
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +641 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +165 -0
- package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +221 -0
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +195 -0
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +167 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +74 -15
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +9 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +5 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +13 -3
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-lifecycle-epoch.mjs +0 -8
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +44 -16
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -5
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +39 -4
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -5
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +55 -8
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +58 -0
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +24 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +32 -5
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +70 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +277 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +28 -9
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -12
- package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +46 -0
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +0 -4
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +44 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +12 -0
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-client.mjs +113 -5
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +4 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +25 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +6 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +3 -0
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +75 -57
- package/src/runtime/browser-bridge/client.mjs +24 -0
- package/src/runtime/channels/lib/scheduler.mjs +40 -12
- package/src/runtime/channels/lib/schedules-db.mjs +71 -12
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +36 -16
- package/src/runtime/channels/lib/webhook.mjs +0 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +100 -10
- package/src/runtime/channels/lib/worker-main.mjs +17 -20
- package/src/runtime/computer-bridge/client.mjs +28 -1
- package/src/runtime/connectors/gmail-app-password.mjs +690 -0
- package/src/runtime/connectors/google-mcp.mjs +446 -0
- package/src/runtime/memory/lib/core-memory-access.mjs +69 -0
- package/src/runtime/memory/lib/core-memory-file.mjs +16 -8
- package/src/runtime/memory/lib/core-memory-index.mjs +15 -9
- package/src/runtime/memory/lib/core-memory-management.mjs +10 -4
- package/src/runtime/memory/lib/core-memory-store.mjs +53 -30
- package/src/runtime/memory/lib/core-memory-uniqueness.mjs +10 -6
- package/src/runtime/memory/lib/http-router/session-routes.mjs +3 -2
- package/src/runtime/memory/lib/memory-action-handlers/core-actions.mjs +44 -14
- package/src/runtime/memory/lib/memory-schema/core-and-meta.mjs +11 -0
- package/src/runtime/memory/lib/memory.mjs +7 -1
- package/src/runtime/memory/lib/query-core-recall.mjs +9 -1
- package/src/runtime/memory/lib/query-hybrid-search.mjs +2 -0
- package/src/runtime/memory/lib/tool-call-handler.mjs +2 -0
- package/src/runtime/memory/tool-defs.mjs +5 -0
- package/src/runtime/shared/agent-avatar-sprites.mjs +445 -0
- package/src/runtime/shared/agent-avatar.d.mts +64 -0
- package/src/runtime/shared/agent-avatar.mjs +320 -0
- package/src/runtime/shared/agent-route-config.d.mts +3 -0
- package/src/runtime/shared/agent-route-config.mjs +16 -0
- package/src/runtime/shared/atomic-file.mjs +14 -1
- package/src/runtime/shared/config.mjs +8 -1
- package/src/runtime/shared/connector-accounts.mjs +15 -0
- package/src/runtime/shared/connector-catalog.d.mts +52 -0
- package/src/runtime/shared/connector-catalog.mjs +230 -0
- package/src/runtime/shared/connector-triggers.d.mts +3 -0
- package/src/runtime/shared/connector-triggers.mjs +43 -0
- package/src/runtime/shared/google-oauth-client.mjs +24 -0
- package/src/runtime/shared/held-request-host.d.mts +12 -0
- package/src/runtime/shared/held-request-host.mjs +71 -0
- package/src/runtime/shared/plain-preview.d.mts +1 -0
- package/src/runtime/shared/plain-preview.mjs +28 -0
- package/src/runtime/shared/routine-limits.d.mts +11 -0
- package/src/runtime/shared/routine-limits.mjs +21 -0
- package/src/runtime/shared/routine-trigger.d.mts +10 -0
- package/src/runtime/shared/routine-trigger.mjs +44 -0
- package/src/runtime/shared/schedule-model-ref.mjs +9 -10
- package/src/runtime/shared/slow-span.mjs +4 -12
- package/src/runtime/shared/statusline/statusline-segments.mjs +13 -1
- package/src/runtime/shared/transcript-metadata.mjs +10 -0
- package/src/runtime/shared/turn-changes.mjs +0 -8
- package/src/runtime/shared/usage-readout-totals.mjs +56 -0
- package/src/runtime/shared/user-data-guard.mjs +114 -36
- package/src/session-runtime/agent-home-delivery.mjs +459 -0
- package/src/session-runtime/agent-profile-changes.mjs +21 -0
- package/src/session-runtime/agent-room-delivery.mjs +92 -0
- package/src/session-runtime/agent-task-sessions.mjs +200 -0
- package/src/session-runtime/boot/apis.mjs +50 -18
- package/src/session-runtime/boot/facade.mjs +5 -8
- package/src/session-runtime/boot/infrastructure.mjs +28 -17
- package/src/session-runtime/boot/tools.mjs +3 -0
- package/src/session-runtime/channel-config-api.mjs +53 -5
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +36 -20
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +6 -1
- package/src/session-runtime/held-requests.mjs +228 -0
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +121 -0
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +31 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +31 -2
- package/src/session-runtime/internal-tool-executor.mjs +2 -0
- package/src/session-runtime/lifecycle/session-catalog.mjs +9 -0
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +4 -0
- package/src/session-runtime/lifecycle/shared.mjs +6 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +8 -0
- package/src/session-runtime/mcp-glue/server-input.mjs +3 -0
- package/src/session-runtime/mcp-oauth-login.mjs +112 -15
- package/src/session-runtime/model-route/set-route.mjs +14 -3
- package/src/session-runtime/owned-automation-run.mjs +229 -0
- package/src/session-runtime/resource-api.mjs +5 -0
- package/src/session-runtime/resource-mcp-api.mjs +107 -13
- package/src/session-runtime/resource-skills-api.mjs +12 -0
- package/src/session-runtime/room-member-gate.mjs +48 -0
- package/src/session-runtime/routine-home-turn.mjs +156 -0
- package/src/session-runtime/routine-owner.mjs +48 -0
- package/src/session-runtime/schedule-session-run.mjs +30 -64
- package/src/session-runtime/services/agent-tool/helpers.mjs +10 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +19 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +2 -0
- package/src/session-runtime/services/channel-admin.mjs +93 -24
- package/src/session-runtime/services/memory-access.mjs +37 -0
- package/src/session-runtime/services/provider-admin.mjs +74 -39
- package/src/session-runtime/services/schedule-access.mjs +91 -0
- package/src/session-runtime/session-create/session-options.mjs +34 -7
- package/src/session-runtime/session-hooks.mjs +16 -8
- package/src/session-runtime/setup-tool/executor.mjs +68 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +72 -14
- package/src/session-runtime/setup-tool/settings-contract.mjs +8 -6
- package/src/session-runtime/setup-tool/tool-defs.mjs +8 -0
- package/src/session-runtime/skills-api.mjs +16 -1
- package/src/session-runtime/tool-policy-refresh.mjs +238 -29
- package/src/session-runtime/turn/session-ops.mjs +8 -1
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +10 -2
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +3 -0
- package/src/session-runtime/webhook-session-run.mjs +49 -67
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +239 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +556 -22
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +11 -1
- package/src/session-runtime/workflow-agents-api.mjs +4 -1
- package/src/standalone/daemon-agent-control.mjs +1 -8
- package/src/standalone/daemon-session-control.mjs +11 -2
- package/src/standalone/daemon.mjs +18 -4
- package/src/standalone/session-protocol.mjs +27 -0
- package/src/standalone/session-service/session-calls/session-turns.mjs +9 -0
- package/src/standalone/session-service.mjs +19 -0
- package/src/tui/app/slash-commands.mjs +20 -0
- package/src/tui/dist/index.mjs +164 -86
- package/src/tui/session/context-state.mjs +6 -1
- package/src/tui/session/notice-surface.mjs +35 -4
- package/src/tui/session/queue-helpers.mjs +2 -1
- package/src/tui/session/session-api/extensions.mjs +4 -0
- package/src/tui/session/session-api/intake/submission.mjs +5 -0
- package/src/tui/session/session-api/integrations.mjs +8 -0
- package/src/tui/session/session-api/lifecycle/session-reset.mjs +13 -3
- package/src/tui/session/session-api/lifecycle.mjs +17 -1
- package/src/tui/session/session-api/routes.mjs +48 -3
- package/src/tui/session/session-flow/drain.mjs +12 -3
- package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -1
- package/src/tui/session/session-flow/queue/take-entries.mjs +3 -2
- package/src/tui/session/session-flow/steering.mjs +58 -24
- package/src/tui/session/tool-approval.mjs +26 -5
- package/src/tui/session/transcript-intake.mjs +6 -2
- package/src/tui/session/transcript-spill.mjs +5 -1
- package/src/tui/session/tui-steering-persist.mjs +65 -42
- package/src/tui/session/turn-live-call.mjs +56 -0
- package/src/tui/session/turn.mjs +22 -6
- package/src/session-runtime/automation-agents.mjs +0 -94
- package/src/session-runtime/automation-workflow.mjs +0 -59
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// message-array change detect, tool-kind classification, skills, hook overrides,
|
|
3
3
|
// native tool-search payload parsing, bash-session routing, and approval.
|
|
4
4
|
import { isMcpTool } from '../../mcp/client.mjs';
|
|
5
|
+
import { unattendedApprovalPort } from '../human-gate/gate.mjs';
|
|
5
6
|
import { isBuiltinTool } from '../../tools/builtin.mjs';
|
|
6
7
|
import { isInternalTool } from '../../internal-tools.mjs';
|
|
7
8
|
import { loadSkillToolDependencies } from '../../runtime-core/skill-tool-loading.mjs';
|
|
@@ -207,15 +208,24 @@ export async function resolvePreToolAskApproval({
|
|
|
207
208
|
toolCallId,
|
|
208
209
|
askReason,
|
|
209
210
|
toolApprovalHook,
|
|
211
|
+
request = null,
|
|
210
212
|
}) {
|
|
211
213
|
const name = String(toolName || 'tool');
|
|
212
214
|
const reason = String(askReason || 'approval requested by hook').trim();
|
|
213
|
-
|
|
215
|
+
// Unattended runs never auto-approve and have no card: a schedule or webhook
|
|
216
|
+
// run always holds the request for its owner; a room member does when no
|
|
217
|
+
// approval UI is attached (session-runtime/held-requests.mjs).
|
|
218
|
+
const unattended = unattendedApprovalPort();
|
|
219
|
+
const run = unattended?.runOf?.(sessionId) || null;
|
|
220
|
+
const held = run && (run.kind !== 'room' || typeof toolApprovalHook !== 'function');
|
|
221
|
+
const ask = held ? unattended.hold : toolApprovalHook;
|
|
222
|
+
if (typeof ask !== 'function') {
|
|
214
223
|
return { denial: formatMissingToolApprovalUiDenial(name, reason) };
|
|
215
224
|
}
|
|
216
225
|
let approval;
|
|
217
226
|
try {
|
|
218
|
-
approval = await
|
|
227
|
+
approval = await ask({
|
|
228
|
+
...(request || {}),
|
|
219
229
|
name,
|
|
220
230
|
args,
|
|
221
231
|
cwd,
|
|
@@ -229,7 +239,7 @@ export async function resolvePreToolAskApproval({
|
|
|
229
239
|
}
|
|
230
240
|
if (!approvalGranted(approval)) {
|
|
231
241
|
const detail = approvalReason(approval, reason || 'not approved');
|
|
232
|
-
return { denial: `Error: tool "${name}" denied by hook: ${detail}
|
|
242
|
+
return { denial: `Error: tool "${name}" denied by hook: ${detail}`, approval };
|
|
233
243
|
}
|
|
234
244
|
return { approval };
|
|
235
245
|
}
|
|
@@ -41,6 +41,7 @@ export function usageDeltaEvent({
|
|
|
41
41
|
usage,
|
|
42
42
|
sendTools,
|
|
43
43
|
toolCalls = 0,
|
|
44
|
+
generationMs = 0,
|
|
44
45
|
}) {
|
|
45
46
|
return {
|
|
46
47
|
sessionId,
|
|
@@ -56,6 +57,12 @@ export function usageDeltaEvent({
|
|
|
56
57
|
deltaToolCalls: toolCalls,
|
|
57
58
|
...reasoningUsage(usage),
|
|
58
59
|
deltaPrompt: usage.promptTokens || 0,
|
|
60
|
+
// First visible token → end of this response; 0 when the call was not
|
|
61
|
+
// timed (nothing visible streamed). Only timed output enters speed figures.
|
|
62
|
+
generationMs,
|
|
63
|
+
// A provider that cannot measure the prompt or its cache split says so;
|
|
64
|
+
// its zeros are unknowns, not readings (no cache hit can be derived).
|
|
65
|
+
promptKnown: usage.inputTokensKnown !== false && usage.cacheTokensKnown !== false,
|
|
59
66
|
// Cache delta carried alongside input/output so live metrics reflect
|
|
60
67
|
// the same token classes the terminal aggregate adds; additive —
|
|
61
68
|
// callers that ignore these fields keep working.
|
|
@@ -186,6 +186,7 @@ export async function prepareAskTurn({ sessionId, opened, input, cwdOverride, tr
|
|
|
186
186
|
beforeCount: historyMessages.length + 1,
|
|
187
187
|
deferredToolDelta: userTurn.deferredToolDelta,
|
|
188
188
|
goalReminder: userTurn.goalReminder,
|
|
189
|
+
workflowNotice: userTurn.workflowNotice,
|
|
189
190
|
workspaceNotice: userTurn.workspaceNotice,
|
|
190
191
|
setupNotice: userTurn.setupNotice,
|
|
191
192
|
};
|
|
@@ -8,6 +8,7 @@ import { createAskSteeringDrain } from './ask-turn-steering-drain.mjs';
|
|
|
8
8
|
import { updateSessionStage, markSessionStreamDelta } from './runtime-liveness.mjs';
|
|
9
9
|
import { codexWireSendOpts } from './session-id.mjs';
|
|
10
10
|
import { persistIterationMetrics } from './usage-metrics.mjs';
|
|
11
|
+
import { isAgentModeSession } from '../agent-mode.mjs';
|
|
11
12
|
|
|
12
13
|
const optionalFn = (value) => (typeof value === 'function' ? value : undefined);
|
|
13
14
|
const relay = (fn, ...args) => {
|
|
@@ -184,7 +185,8 @@ export function buildAgentLoopOptions({
|
|
|
184
185
|
onCompactEvent: (event) => {
|
|
185
186
|
checkpoint.refreshContextState();
|
|
186
187
|
checkpoint.schedule(true);
|
|
187
|
-
|
|
188
|
+
// Agent mode compacts silently: no compaction notice reaches the host.
|
|
189
|
+
if (!isAgentModeSession(session)) relay(askOpts?.onCompactEvent, event);
|
|
188
190
|
},
|
|
189
191
|
// Pre-send gauge sync. Defined only when a host listens so the loop
|
|
190
192
|
// never computes a display number nobody reads.
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
snapshotPendingWorkspaceNotice,
|
|
20
20
|
snapshotPendingSetupNotice,
|
|
21
21
|
} from './prompt-utils.mjs';
|
|
22
|
+
import { snapshotPendingWorkflowNotice } from './workflow-switch-notice.mjs';
|
|
22
23
|
import { codexWireSendOpts } from './session-id.mjs';
|
|
23
24
|
import { _tryBridgeExplicitPrefetch } from './prefetch-bridge.mjs';
|
|
24
25
|
import { filterModelVisibleSessionMessages } from './message-sanitize.mjs';
|
|
@@ -180,7 +181,11 @@ export async function buildUserTurn({
|
|
|
180
181
|
const workspaceNotice = snapshotPendingWorkspaceNotice(session);
|
|
181
182
|
// What preparing a new worktree linked, installed, ran, failed or skipped.
|
|
182
183
|
const setupNotice = snapshotPendingSetupNotice(session);
|
|
184
|
+
// A mid-conversation workflow switch: the prompt and tools were rebuilt
|
|
185
|
+
// for the new workflow; this turn tells the model once.
|
|
186
|
+
const workflowNotice = snapshotPendingWorkflowNotice(session);
|
|
183
187
|
const reminderBlock = [
|
|
188
|
+
workflowNotice?.content || '',
|
|
184
189
|
workspaceNotice?.content || '',
|
|
185
190
|
setupNotice?.content || '',
|
|
186
191
|
currentTimeBlock ? `<system-reminder>\n# Current Time\n${currentTimeBlock}\n</system-reminder>` : '',
|
|
@@ -209,6 +214,7 @@ export async function buildUserTurn({
|
|
|
209
214
|
historyMessages,
|
|
210
215
|
deferredToolDelta,
|
|
211
216
|
goalReminder,
|
|
217
|
+
workflowNotice,
|
|
212
218
|
workspaceNotice,
|
|
213
219
|
setupNotice,
|
|
214
220
|
userTurnMessage,
|
|
@@ -9,6 +9,7 @@ import { persistedAssistantTranscriptMetadata } from '../../../../shared/transcr
|
|
|
9
9
|
import { acknowledgePendingDeferredToolDelta } from '../../runtime-core/deferred-tool-delta.mjs';
|
|
10
10
|
import { acknowledgePendingGoalReminder } from '../../runtime-core/goal-reminder.mjs';
|
|
11
11
|
import { acknowledgePendingSetupNotice, acknowledgePendingWorkspaceNotice } from './prompt-utils.mjs';
|
|
12
|
+
import { acknowledgePendingWorkflowNotice } from './workflow-switch-notice.mjs';
|
|
12
13
|
import {
|
|
13
14
|
finalizePendingMessageDelivery,
|
|
14
15
|
drainPendingMessages,
|
|
@@ -139,6 +140,7 @@ export async function commitAskTurn({ sessionId, opened, prepared, result, rawTr
|
|
|
139
140
|
if (prepared.goalReminder) {
|
|
140
141
|
acknowledgePendingGoalReminder(session, prepared.goalReminder.revision);
|
|
141
142
|
}
|
|
143
|
+
if (prepared.workflowNotice) acknowledgePendingWorkflowNotice(session, prepared.workflowNotice.revision);
|
|
142
144
|
if (prepared.workspaceNotice) {
|
|
143
145
|
acknowledgePendingWorkspaceNotice(session, prepared.workspaceNotice.revision);
|
|
144
146
|
}
|
|
@@ -40,14 +40,6 @@ export function currentPendingLifecycleToken(sessionId) {
|
|
|
40
40
|
return pendingLifecycleToken(pendingSessionLifecycle(sessionId));
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
// Refusal verdict of the lifecycle a token was minted from (tombstoned or
|
|
44
|
-
// unreadable) — exactly pendingLifecycleInvalidated(sessionId) for that same
|
|
45
|
-
// read, so a caller holding a fresh token needs no second durable read.
|
|
46
|
-
export function lifecycleTokenClosed(token) {
|
|
47
|
-
const { source } = parseLifecycleToken(token);
|
|
48
|
-
return source === 'closed' || source === 'unreadable';
|
|
49
|
-
}
|
|
50
|
-
|
|
51
43
|
// Parses a `source:generation` epoch token.
|
|
52
44
|
function parseLifecycleToken(token) {
|
|
53
45
|
const text = String(token);
|
|
@@ -207,29 +207,46 @@ function bp3SliceAt(text, heading) {
|
|
|
207
207
|
|
|
208
208
|
/**
|
|
209
209
|
* Replace the workspace-scoped tail of a BP3 core (composeSystemPrompt order:
|
|
210
|
-
* …, `#
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
210
|
+
* …, `# Instruction Files`, `# Core Memory`). Core memory is the last,
|
|
211
|
+
* separator-free part; the instruction-files slice before it may itself
|
|
212
|
+
* contain separators, so both are cut by position. A core from before that
|
|
213
|
+
* order (memory, then instruction files) is read too and written in the
|
|
214
|
+
* current order. `undefined` keeps a slice, an empty string drops it.
|
|
214
215
|
* @param {string} core
|
|
215
216
|
* @param {{ coreMemoryContext?: string, instructionFilesContext?: string }} slices
|
|
216
217
|
*/
|
|
217
218
|
export function replaceWorkspaceCoreSlices(core, { coreMemoryContext, instructionFilesContext } = {}) {
|
|
219
|
+
let { head, instructionFiles, memory } = splitWorkspaceCoreSlices(core);
|
|
220
|
+
if (coreMemoryContext !== undefined) {
|
|
221
|
+
const value = trimmedSlice(coreMemoryContext);
|
|
222
|
+
memory = value ? `${CORE_MEMORY_HEADING}${value}` : '';
|
|
223
|
+
}
|
|
224
|
+
if (instructionFilesContext !== undefined) instructionFiles = trimmedSlice(instructionFilesContext);
|
|
225
|
+
return [head, instructionFiles, memory].filter((part) => part?.trim()).join(BP3_PART_SEPARATOR);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** A BP3 core's `{ head, instructionFiles, memory }` (each '' when absent). */
|
|
229
|
+
function splitWorkspaceCoreSlices(core) {
|
|
218
230
|
let head = String(core || '');
|
|
231
|
+
let memory = '';
|
|
232
|
+
const memoryAt = bp3SliceAt(head, CORE_MEMORY_HEADING);
|
|
233
|
+
if (memoryAt) {
|
|
234
|
+
memory = head.slice(memoryAt.start);
|
|
235
|
+
head = head.slice(0, memoryAt.cut);
|
|
236
|
+
const legacy = memory.indexOf(`${BP3_PART_SEPARATOR}${INSTRUCTION_FILES_HEADING}`);
|
|
237
|
+
if (legacy >= 0) {
|
|
238
|
+
const instructions = memory.slice(legacy + BP3_PART_SEPARATOR.length);
|
|
239
|
+
memory = memory.slice(0, legacy);
|
|
240
|
+
head = head ? `${head}${BP3_PART_SEPARATOR}${instructions}` : instructions;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
219
243
|
let instructionFiles = '';
|
|
220
244
|
const instructionAt = bp3SliceAt(head, INSTRUCTION_FILES_HEADING);
|
|
221
245
|
if (instructionAt) {
|
|
222
246
|
instructionFiles = head.slice(instructionAt.start);
|
|
223
247
|
head = head.slice(0, instructionAt.cut);
|
|
224
248
|
}
|
|
225
|
-
|
|
226
|
-
if (coreMemoryContext !== undefined) {
|
|
227
|
-
parts = parts.filter((part) => !part.startsWith(CORE_MEMORY_HEADING));
|
|
228
|
-
const memory = trimmedSlice(coreMemoryContext);
|
|
229
|
-
if (memory) parts.push(`${CORE_MEMORY_HEADING}${memory}`);
|
|
230
|
-
}
|
|
231
|
-
if (instructionFilesContext !== undefined) instructionFiles = trimmedSlice(instructionFilesContext);
|
|
232
|
-
return [...parts, instructionFiles].filter((part) => part?.trim()).join(BP3_PART_SEPARATOR);
|
|
249
|
+
return { head, instructionFiles, memory };
|
|
233
250
|
}
|
|
234
251
|
|
|
235
252
|
/**
|
|
@@ -286,9 +303,7 @@ function textOf(message) {
|
|
|
286
303
|
*/
|
|
287
304
|
function presentedWorkspace(session) {
|
|
288
305
|
const core = session.bp3EnvSplit === true ? textOf(bp3SystemMessage(session)) : String(session.bp3CoreContext || '');
|
|
289
|
-
const
|
|
290
|
-
const head = instructionAt ? core.slice(0, instructionAt.cut) : core;
|
|
291
|
-
const memory = (head ? head.split(BP3_PART_SEPARATOR) : []).find((part) => part.startsWith(CORE_MEMORY_HEADING));
|
|
306
|
+
const { instructionFiles, memory } = splitWorkspaceCoreSlices(core);
|
|
292
307
|
const tail = typeof session.bp3EnvironmentContext === 'string' ? session.bp3EnvironmentContext : '';
|
|
293
308
|
const facts = tail.split(BP3_PART_SEPARATOR)[0] || '';
|
|
294
309
|
const promptText = [textOf(bpEnvSystemMessage(session)), textOf(bp3SystemMessage(session))].join('\n');
|
|
@@ -297,10 +312,23 @@ function presentedWorkspace(session) {
|
|
|
297
312
|
cwd: cwd ? cwd.trim() : null,
|
|
298
313
|
environmentContext: facts.startsWith('- ') ? facts.trim() : '',
|
|
299
314
|
coreMemoryContext: memory ? memory.slice(CORE_MEMORY_HEADING.length).trim() : '',
|
|
300
|
-
instructionFilesContext:
|
|
315
|
+
instructionFilesContext: instructionFiles.trim(),
|
|
301
316
|
};
|
|
302
317
|
}
|
|
303
318
|
|
|
319
|
+
/**
|
|
320
|
+
* A rebuilt BP3 core head (composed without workspace slices) followed by the
|
|
321
|
+
* instruction-files and core-memory slices the session's prompt presents now,
|
|
322
|
+
* so a rebuild of the rest of the core (a mid-conversation workflow switch)
|
|
323
|
+
* leaves what the model was told about its workspace — and any staged
|
|
324
|
+
* workspaceReroot — as it was.
|
|
325
|
+
*/
|
|
326
|
+
export function withPresentedWorkspaceSlices(session, nextHead) {
|
|
327
|
+
const core = session.bp3EnvSplit === true ? textOf(bp3SystemMessage(session)) : String(session.bp3CoreContext || '');
|
|
328
|
+
const { instructionFiles, memory } = splitWorkspaceCoreSlices(core);
|
|
329
|
+
return [nextHead, instructionFiles, memory].filter((part) => part?.trim()).join(BP3_PART_SEPARATOR);
|
|
330
|
+
}
|
|
331
|
+
|
|
304
332
|
const WORKSPACE_SLICES = ['environmentContext', 'coreMemoryContext', 'instructionFilesContext'];
|
|
305
333
|
|
|
306
334
|
/**
|
|
@@ -112,20 +112,36 @@ export function _buildAgentRules(profile = 'full') {
|
|
|
112
112
|
);
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
// One `part` of LEAD.md (rules-builder buildLeadRoleContent): 'common' (the
|
|
116
|
+
// lines every Lead shares), 'coding' / 'agent' (the mode-variant passages),
|
|
117
|
+
// 'identity' (the coding identity sentence).
|
|
118
|
+
export function _buildLeadRules({ includeLeadBrief = true, part = 'common' } = {}) {
|
|
116
119
|
const PLUGIN_ROOT = mixdogRoot();
|
|
117
120
|
const DATA_DIR = resolvePluginData();
|
|
118
121
|
const RULES_DIR = join(PLUGIN_ROOT, 'rules');
|
|
122
|
+
const variant = includeLeadBrief ? 'delegating' : 'delegation-free';
|
|
119
123
|
return buildCachedRules(
|
|
120
124
|
'buildLeadRoleContent',
|
|
121
125
|
'lead role rules',
|
|
122
126
|
[join(RULES_DIR, 'lead'), join(DATA_DIR, 'mixdog-config.json')],
|
|
123
|
-
{ PLUGIN_ROOT, DATA_DIR, includeLeadBrief },
|
|
124
|
-
|
|
127
|
+
{ PLUGIN_ROOT, DATA_DIR, includeLeadBrief, part },
|
|
128
|
+
`${variant}\n${part}`
|
|
125
129
|
);
|
|
126
130
|
}
|
|
127
131
|
|
|
128
|
-
|
|
132
|
+
// One agent-mode rule file (rules/agent-mode): 'conduct', 'mixy' or 'routine'.
|
|
133
|
+
export function _buildAgentModeRules({ part = 'conduct' } = {}) {
|
|
134
|
+
const PLUGIN_ROOT = mixdogRoot();
|
|
135
|
+
return buildCachedRules(
|
|
136
|
+
'buildAgentModeContent',
|
|
137
|
+
'agent mode rules',
|
|
138
|
+
[join(PLUGIN_ROOT, 'rules', 'agent-mode')],
|
|
139
|
+
{ PLUGIN_ROOT, part },
|
|
140
|
+
part
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function _buildLeadMetaContext({ includeOutputStyle = true } = {}) {
|
|
129
145
|
const PLUGIN_ROOT = mixdogRoot();
|
|
130
146
|
const DATA_DIR = resolvePluginData();
|
|
131
147
|
const RULES_DIR = join(PLUGIN_ROOT, 'rules');
|
|
@@ -138,7 +154,8 @@ export function _buildLeadMetaContext() {
|
|
|
138
154
|
join(PLUGIN_ROOT, 'output-styles'),
|
|
139
155
|
join(DATA_DIR, 'output-styles'),
|
|
140
156
|
],
|
|
141
|
-
{ PLUGIN_ROOT, DATA_DIR }
|
|
157
|
+
{ PLUGIN_ROOT, DATA_DIR, includeOutputStyle },
|
|
158
|
+
includeOutputStyle ? 'style' : 'no-style'
|
|
142
159
|
);
|
|
143
160
|
}
|
|
144
161
|
|
|
@@ -28,6 +28,7 @@ import { mintSessionId } from './session-id.mjs';
|
|
|
28
28
|
import { hideCompactionArchive } from '../compaction-archive-capture.mjs';
|
|
29
29
|
import { writeStderrBestEffort } from '../../../../shared/best-effort-stderr.mjs';
|
|
30
30
|
import { forgetSideQuestion } from '../side-question-store.mjs';
|
|
31
|
+
import { isAgentHomeSessionId } from '../agent-home.mjs';
|
|
31
32
|
|
|
32
33
|
/** Force-flush session metrics to disk. */
|
|
33
34
|
export async function flushSessionMetrics(sessionId) {
|
|
@@ -207,9 +208,12 @@ function clearTokenAccounting(session, messages, keep, beforeMessageTokens) {
|
|
|
207
208
|
// Fork the outgoing transcript to a separate resumable session BEFORE the wipe,
|
|
208
209
|
// so the conversation about to be discarded stays reachable via /resume under a
|
|
209
210
|
// fresh id. Best-effort: any failure here must never block the clear itself.
|
|
210
|
-
|
|
211
|
+
// `archiveAs` names the fork (an agent home's "대화 새로 시작": the host
|
|
212
|
+
// archives that id before the clear) and makes it durable first: the returned
|
|
213
|
+
// promise settles once the copy is on disk, and the wipe waits on it.
|
|
214
|
+
function forkOutgoingTranscript(session, messages, now, archiveAs = '') {
|
|
211
215
|
try {
|
|
212
|
-
const forkId = mintSessionId();
|
|
216
|
+
const forkId = archiveAs || mintSessionId();
|
|
213
217
|
const fork = {
|
|
214
218
|
...session,
|
|
215
219
|
id: forkId,
|
|
@@ -234,6 +238,15 @@ function forkOutgoingTranscript(session, messages, now) {
|
|
|
234
238
|
delete fork.compaction.archive;
|
|
235
239
|
}
|
|
236
240
|
setLiveSession(fork);
|
|
241
|
+
if (archiveAs) {
|
|
242
|
+
return saveSessionAsync(fork).then(
|
|
243
|
+
() => evictLiveSession(forkId),
|
|
244
|
+
(err) => {
|
|
245
|
+
evictLiveSession(forkId);
|
|
246
|
+
throw err;
|
|
247
|
+
}
|
|
248
|
+
);
|
|
249
|
+
}
|
|
237
250
|
void saveSessionAsync(fork)
|
|
238
251
|
.then(() => {
|
|
239
252
|
// The fork is a cold snapshot kept for /resume. Once durable on
|
|
@@ -247,17 +260,33 @@ function forkOutgoingTranscript(session, messages, now) {
|
|
|
247
260
|
writeStderrBestEffort(`[session] clear-fork save failed (sess=${forkId}): ${err?.message || err}\n`);
|
|
248
261
|
});
|
|
249
262
|
} catch (err) {
|
|
263
|
+
if (archiveAs) throw err;
|
|
250
264
|
writeStderrBestEffort(`[session] clear-fork failed (sess=${session.id}): ${err?.message || err}\n`);
|
|
251
265
|
}
|
|
252
266
|
}
|
|
253
267
|
|
|
268
|
+
const ARCHIVE_ID = /^sess_[A-Za-z0-9_-]{8,200}$/;
|
|
269
|
+
|
|
270
|
+
/** The fork id a clear was asked to archive under, '' when none. */
|
|
271
|
+
function clearArchiveId(value, sessionId) {
|
|
272
|
+
if (value === undefined || value === null || value === '') return '';
|
|
273
|
+
const id = String(value);
|
|
274
|
+
if (!ARCHIVE_ID.test(id) || id === sessionId || isAgentHomeSessionId(id)) {
|
|
275
|
+
throw new Error('clear: archiveAs must be a fresh session id');
|
|
276
|
+
}
|
|
277
|
+
if (loadSession(id)) throw new Error(`clear: session ${id} already exists`);
|
|
278
|
+
return id;
|
|
279
|
+
}
|
|
280
|
+
|
|
254
281
|
export async function clearSessionMessages(sessionId, options = {}) {
|
|
255
282
|
const session = loadSession(sessionId);
|
|
256
283
|
if (!session) return false;
|
|
257
284
|
// Don't resurrect a closed session just to clear its messages.
|
|
258
285
|
if (session.closed === true) return false;
|
|
259
286
|
const clearOptions = options && typeof options === 'object' ? options : {};
|
|
260
|
-
const
|
|
287
|
+
const archiveAs = clearArchiveId(clearOptions.archiveAs, sessionId);
|
|
288
|
+
// An archived reset keeps the whole transcript: never compacted first.
|
|
289
|
+
const compact = clearOptions.compact === true && !archiveAs;
|
|
261
290
|
const currentMessages = Array.isArray(session.messages) ? session.messages : [];
|
|
262
291
|
const beforeMessageTokens = estimateMessagesTokens(currentMessages);
|
|
263
292
|
const { messages, clearCompactError } = compact
|
|
@@ -275,8 +304,14 @@ export async function clearSessionMessages(sessionId, options = {}) {
|
|
|
275
304
|
// content the live session retains via the summary, so the fork duplicated
|
|
276
305
|
// it as a confusing extra Recent row ("Re-attached after compaction…" —
|
|
277
306
|
// user report). Plain /clear (no summary kept) still forks.
|
|
307
|
+
// `fork: false` (a room member's reset: the room's own log keeps the
|
|
308
|
+
// conversation) skips the copy; an `archiveAs` clear always keeps one.
|
|
278
309
|
const summaryCarriedForward = keep.some(isCompactSummaryMessage);
|
|
279
|
-
|
|
310
|
+
const keepCopy = clearOptions.fork !== false || Boolean(archiveAs);
|
|
311
|
+
if (keepCopy && hasUserConversationMessage(messages) && !summaryCarriedForward) {
|
|
312
|
+
const fork = forkOutgoingTranscript(session, messages, now, archiveAs);
|
|
313
|
+
if (archiveAs) await fork;
|
|
314
|
+
}
|
|
280
315
|
|
|
281
316
|
session.messages = keep;
|
|
282
317
|
// Clear truncates the transcript wholesale; drop the provider prefix
|
|
@@ -9,6 +9,7 @@ import { saveSession, saveSessionAsync, saveSessionAsyncDeferred, loadSession, s
|
|
|
9
9
|
import { _liveSessions } from '../store/live-state.mjs';
|
|
10
10
|
import { _recoverTurnCheckpointDurably } from './turn-checkpoint-recovery.mjs';
|
|
11
11
|
import { isAgentOwner } from '../../agent-owner.mjs';
|
|
12
|
+
import { AGENT_MODE, resolveSessionMode, sessionModeOf } from '../agent-mode.mjs';
|
|
12
13
|
import { getHiddenAgent } from '../../internal-agents.mjs';
|
|
13
14
|
import { loadConfig } from '../../config.mjs';
|
|
14
15
|
import {
|
|
@@ -19,6 +20,7 @@ import {
|
|
|
19
20
|
import { normalizeAutoClearConfig, resolveAutoClearIdleMs } from '../../runtime-core/config-helpers.mjs';
|
|
20
21
|
import { _buildBaseRules } from './rules-cache.mjs';
|
|
21
22
|
import { composeSessionSystem, seedSessionMessages } from './session-prompt-composition.mjs';
|
|
23
|
+
import { agentProfileRevision, leadRosterRevision } from '../../context/role-instructions.mjs';
|
|
22
24
|
import {
|
|
23
25
|
_prepareResumeTools,
|
|
24
26
|
delegationDisabled,
|
|
@@ -206,12 +208,22 @@ function logSessionSurface({ resolvedAgent, toolPermission, tools }) {
|
|
|
206
208
|
}
|
|
207
209
|
}
|
|
208
210
|
|
|
209
|
-
export function createSession(
|
|
210
|
-
const presetObj =
|
|
211
|
-
const resolved = resolveAgentRuntimeProfile(
|
|
211
|
+
export function createSession(createOpts) {
|
|
212
|
+
const presetObj = createOpts.preset && typeof createOpts.preset === 'object' ? createOpts.preset : null;
|
|
213
|
+
const resolved = resolveAgentRuntimeProfile(createOpts, presetObj);
|
|
212
214
|
const { profile } = resolved;
|
|
213
|
-
const route = resolveSessionRoute(
|
|
215
|
+
const route = resolveSessionRoute(createOpts, presetObj, profile);
|
|
214
216
|
const { providerName, modelName, provider, toolPreset, id } = route;
|
|
217
|
+
// Agent or coding mode (agent-mode.mjs), resolved once and persisted. An
|
|
218
|
+
// agent-mode Lead acts as its agent: a schedule/webhook run that names only
|
|
219
|
+
// its `ownerAgentId` gets that agent's role, persona and connector policy
|
|
220
|
+
// (all keyed by `session.agent`), as its home thread does.
|
|
221
|
+
const sessionMode = sessionModeOf({ ...createOpts, id });
|
|
222
|
+
const actingAgent = resolveSessionMode({ session: { ...createOpts, id } }).agentId;
|
|
223
|
+
const opts =
|
|
224
|
+
sessionMode === AGENT_MODE && !createOpts.agent && actingAgent
|
|
225
|
+
? { ...createOpts, agent: actingAgent, sessionMode }
|
|
226
|
+
: { ...createOpts, sessionMode };
|
|
215
227
|
const routeFallbacks = normalizeWorkflowRoute({
|
|
216
228
|
provider: providerName,
|
|
217
229
|
model: modelName,
|
|
@@ -227,7 +239,10 @@ export function createSession(opts) {
|
|
|
227
239
|
// Scoped to explicit-breakpoint (Anthropic-family) providers only.
|
|
228
240
|
const providerCacheOpts = resolved.providerCacheOpts || buildSessionProviderCacheOpts(providerName, id, opts.agent);
|
|
229
241
|
const surface = resolveSessionToolSurface(opts, { profile, toolPreset, modelName });
|
|
230
|
-
|
|
242
|
+
// The agent profile the prompt is composed from, read first: an edit landing
|
|
243
|
+
// during composition leaves the stamp behind, never ahead (refreshAgentProfile).
|
|
244
|
+
const agentProfile = surface.ownerIsAgent ? '' : agentProfileRevision(surface.resolvedAgent);
|
|
245
|
+
const prompt = composeSessionSystem(opts, { profile, providerName, modelName, surface, sessionMode });
|
|
231
246
|
const messages = seedSessionMessages(prompt, opts.files);
|
|
232
247
|
logSessionSurface(surface);
|
|
233
248
|
const contextMeta = resolveSessionContextMeta(provider, modelName, {
|
|
@@ -246,6 +261,11 @@ export function createSession(opts) {
|
|
|
246
261
|
origin: sessionOriginFields(opts, { profile, presetObj, providerCacheOpts, surface }),
|
|
247
262
|
});
|
|
248
263
|
session.providerCacheOptsOverride = Boolean(resolved.providerCacheOpts);
|
|
264
|
+
if (agentProfile) {
|
|
265
|
+
session.agentProfileRevision = agentProfile;
|
|
266
|
+
// The bot roster its prompt lists (a Lead's catalog slices).
|
|
267
|
+
session.agentRosterRevision = leadRosterRevision(opts.leadWorkflowParts);
|
|
268
|
+
}
|
|
249
269
|
if (routeFallbacks?.length) session.routeFallbacks = routeFallbacks;
|
|
250
270
|
// A non-native agent sends core + bridge, built from its filtered tools.
|
|
251
271
|
applyAgentToolExposure(session);
|
|
@@ -532,6 +552,8 @@ export async function resumeSession(sessionId, preset, options = {}) {
|
|
|
532
552
|
ensureCodexWireSessionId(session);
|
|
533
553
|
if (!_applyDesktopResumeScope(session, options)) return null;
|
|
534
554
|
if (!session.owner) session.owner = 'user';
|
|
555
|
+
// Records from before the mode existed get it resolved and stamped.
|
|
556
|
+
session.sessionMode = sessionModeOf(session);
|
|
535
557
|
if (Object.hasOwn(options, 'mcpScopeId')) {
|
|
536
558
|
session.mcpScopeId = String(options.mcpScopeId || '').trim() || null;
|
|
537
559
|
}
|
|
@@ -4,9 +4,13 @@
|
|
|
4
4
|
// carry all four to the provider with their cache tiers.
|
|
5
5
|
import { buildSkillManifest, composeSystemPrompt } from '../../context/collect.mjs';
|
|
6
6
|
import { configuredInstructionFilesMode, loadInstructionFilesContext } from '../../context/instruction-files.mjs';
|
|
7
|
+
import { agentModeIdentityLine } from '../../context/role-instructions.mjs';
|
|
8
|
+
import { AGENT_MODE, isRoutineSource, sessionModeOf } from '../agent-mode.mjs';
|
|
9
|
+
import { MIXY_AGENT_ID } from '../agent-home.mjs';
|
|
7
10
|
import {
|
|
8
11
|
_buildBaseRules,
|
|
9
12
|
_buildAgentRules,
|
|
13
|
+
_buildAgentModeRules,
|
|
10
14
|
_buildLeadRules,
|
|
11
15
|
_buildLeadMetaContext,
|
|
12
16
|
_buildLeadLanguageContext,
|
|
@@ -81,8 +85,9 @@ export function buildWorkspacePromptContext(session, cwd) {
|
|
|
81
85
|
];
|
|
82
86
|
return {
|
|
83
87
|
environmentContext: buildShellEnvironmentContext({ cwd }, ownerIsAgent, tools),
|
|
88
|
+
// Agent mode never carries project instruction files.
|
|
84
89
|
instructionFilesContext:
|
|
85
|
-
session?.skipInstructionFiles === true
|
|
90
|
+
session?.skipInstructionFiles === true || sessionModeOf(session) === AGENT_MODE
|
|
86
91
|
? undefined
|
|
87
92
|
: loadInstructionFilesContext({ mode: configuredInstructionFilesMode(), cwd }),
|
|
88
93
|
};
|
|
@@ -90,24 +95,57 @@ export function buildWorkspacePromptContext(session, cwd) {
|
|
|
90
95
|
|
|
91
96
|
// BP1/BP2/BP3 rule blocks plus the volatile environment, composed into the
|
|
92
97
|
// four system blocks; environmentTailContext is the persisted env tail.
|
|
93
|
-
|
|
98
|
+
// A Lead's BP3 rule slices, ordered for prefix sharing (composeSystemPrompt):
|
|
99
|
+
// LEAD.md's common lines first; then the mode block (coding: LEAD.md's two
|
|
100
|
+
// passages; agent mode: their conversational variants and AGENT_MODE.md);
|
|
101
|
+
// then Mixy's MIXY.md; last the per-session tail — routine line, identity.
|
|
102
|
+
// Agent mode is a Lead created as an agent (agent-mode.mjs).
|
|
103
|
+
export function sessionRolePromptFields(
|
|
104
|
+
identity,
|
|
105
|
+
{ ownerIsAgent, toolFreeRole, delegationFree, sessionMode, routine = false }
|
|
106
|
+
) {
|
|
94
107
|
const skipRules = identity.skipAgentRules || toolFreeRole;
|
|
108
|
+
const lead = !ownerIsAgent && !skipRules;
|
|
109
|
+
const agentMode = lead && sessionMode === AGENT_MODE;
|
|
110
|
+
const mixy = (identity.agent || MIXY_AGENT_ID) === MIXY_AGENT_ID;
|
|
95
111
|
let roleRules = '';
|
|
96
112
|
if (!skipRules) {
|
|
97
113
|
roleRules = ownerIsAgent
|
|
98
114
|
? _buildAgentRules(identity.agentRulesProfile)
|
|
99
115
|
: _buildLeadRules({ includeLeadBrief: !delegationFree });
|
|
100
116
|
}
|
|
117
|
+
const identityLine = agentMode
|
|
118
|
+
? agentModeIdentityLine(identity.agent || MIXY_AGENT_ID)
|
|
119
|
+
: lead
|
|
120
|
+
? _buildLeadRules({ includeLeadBrief: !delegationFree, part: 'identity' })
|
|
121
|
+
: '';
|
|
101
122
|
return {
|
|
102
123
|
roleRules,
|
|
124
|
+
...(lead
|
|
125
|
+
? {
|
|
126
|
+
leadModeRules: _buildLeadRules({ includeLeadBrief: !delegationFree, part: agentMode ? 'agent' : 'coding' }),
|
|
127
|
+
identityContext: identityLine ? `# Identity\n\n${identityLine}` : '',
|
|
128
|
+
}
|
|
129
|
+
: {}),
|
|
130
|
+
...(agentMode
|
|
131
|
+
? {
|
|
132
|
+
agentModeRules: _buildAgentModeRules({ part: 'conduct' }),
|
|
133
|
+
...(mixy ? { mixyRules: _buildAgentModeRules({ part: 'mixy' }) } : {}),
|
|
134
|
+
...(routine ? { routineRules: _buildAgentModeRules({ part: 'routine' }) } : {}),
|
|
135
|
+
}
|
|
136
|
+
: {}),
|
|
103
137
|
userPrompt: identity.systemPrompt,
|
|
104
|
-
|
|
138
|
+
// A coding Lead carries no role section; an agent's home thread (a user
|
|
139
|
+
// session running as that agent) carries its own AGENT.md role, and Mixy
|
|
140
|
+
// in agent mode its optional agents/lead/AGENT.md.
|
|
141
|
+
skipRoleCatalog: !ownerIsAgent && (!identity.agent || identity.agent === 'lead') && !(agentMode && mixy),
|
|
105
142
|
agent: identity.agent,
|
|
106
143
|
profile: { skip: identity.profileSkip },
|
|
107
144
|
};
|
|
108
145
|
}
|
|
109
146
|
|
|
110
|
-
export function composeSessionSystem(opts, { profile, providerName, modelName, surface }) {
|
|
147
|
+
export function composeSessionSystem(opts, { profile, providerName, modelName, surface, sessionMode }) {
|
|
148
|
+
const agentMode = sessionMode === AGENT_MODE;
|
|
111
149
|
const { ownerIsAgent, resolvedAgent, skills } = surface;
|
|
112
150
|
// A tool-free hidden role (a one-shot classifier or title writer) carries
|
|
113
151
|
// only its own role rules: the shared tool policy and the worker conduct
|
|
@@ -130,9 +168,15 @@ export function composeSessionSystem(opts, { profile, providerName, modelName, s
|
|
|
130
168
|
agent: resolvedAgent,
|
|
131
169
|
agentRulesProfile: surface.agentRulesProfile,
|
|
132
170
|
};
|
|
133
|
-
const roleFields = sessionRolePromptFields(promptIdentity, {
|
|
171
|
+
const roleFields = sessionRolePromptFields(promptIdentity, {
|
|
172
|
+
ownerIsAgent,
|
|
173
|
+
toolFreeRole,
|
|
174
|
+
delegationFree,
|
|
175
|
+
sessionMode,
|
|
176
|
+
routine: isRoutineSource(opts.sourceType),
|
|
177
|
+
});
|
|
134
178
|
const leadOnly = !skipAgentRules && !ownerIsAgent;
|
|
135
|
-
const metaContext = leadOnly ? _buildLeadMetaContext() : '';
|
|
179
|
+
const metaContext = leadOnly ? _buildLeadMetaContext({ includeOutputStyle: !agentMode }) : '';
|
|
136
180
|
// Lead-only response language; closes the environment block so no English
|
|
137
181
|
// system text (session/shell/git lines) follows it.
|
|
138
182
|
const languageContext = leadOnly ? _buildLeadLanguageContext() : '';
|
|
@@ -146,9 +190,10 @@ export function composeSessionSystem(opts, { profile, providerName, modelName, s
|
|
|
146
190
|
// already sit at the end of this string to stay last after a refresh.
|
|
147
191
|
const environmentTailContext = [shellEnvironmentContext, languageContext].filter(Boolean).join('\n\n---\n\n');
|
|
148
192
|
// User instruction files (AGENTS.md / CLAUDE.md, global then the project
|
|
149
|
-
// root's); a tool-free role
|
|
193
|
+
// root's); a tool-free role, a profile skipping `claudemd` and agent mode
|
|
194
|
+
// get none.
|
|
150
195
|
const instructionFilesContext =
|
|
151
|
-
toolFreeRole || profile?.skip?.claudemd
|
|
196
|
+
toolFreeRole || profile?.skip?.claudemd || agentMode
|
|
152
197
|
? ''
|
|
153
198
|
: loadInstructionFilesContext({ mode: configuredInstructionFilesMode(), cwd: opts.cwd });
|
|
154
199
|
const composed = composeSystemPrompt({
|
|
@@ -157,6 +202,8 @@ export function composeSessionSystem(opts, { profile, providerName, modelName, s
|
|
|
157
202
|
metaContext: metaContext || undefined,
|
|
158
203
|
languageContext: languageContext || undefined,
|
|
159
204
|
workflowContext: opts.workflowContext || null,
|
|
205
|
+
// The workflow's orchestration and agent-catalog slices (workflow/context.mjs leadPromptParts).
|
|
206
|
+
...(ownerIsAgent ? {} : opts.leadWorkflowParts),
|
|
160
207
|
coreMemoryContext: opts.coreMemoryContext || null,
|
|
161
208
|
instructionFilesContext: instructionFilesContext || null,
|
|
162
209
|
skillManifest: buildSkillManifest(skills),
|
|
@@ -70,6 +70,20 @@ export function sessionOriginFields(opts, { profile, presetObj, providerCacheOpt
|
|
|
70
70
|
// scheduler/daily-standup, webhook/github-push, lead/worker.
|
|
71
71
|
sourceType: opts.sourceType || null,
|
|
72
72
|
sourceName: opts.sourceName || null,
|
|
73
|
+
// The agent a schedule/webhook run acts for: whose memory it may write
|
|
74
|
+
// (session-runtime/services/memory-access.mjs). Absent on other sessions.
|
|
75
|
+
...(opts.ownerAgentId ? { ownerAgentId: String(opts.ownerAgentId) } : {}),
|
|
76
|
+
// A coding task session an agent created (session create): who asked, from
|
|
77
|
+
// which thread, the request, and the title it was given.
|
|
78
|
+
...(opts.taskOrigin
|
|
79
|
+
? {
|
|
80
|
+
taskOrigin: opts.taskOrigin,
|
|
81
|
+
title: opts.taskOrigin.title,
|
|
82
|
+
titleLocked: true,
|
|
83
|
+
titleSource: 'ai',
|
|
84
|
+
titleUpdatedAt: Date.now(),
|
|
85
|
+
}
|
|
86
|
+
: {}),
|
|
73
87
|
// Provider-scoped unified cache key — one shard per provider,
|
|
74
88
|
// shared across all roles / sources (agent/maintenance/mcp/
|
|
75
89
|
// scheduler/webhook). Role or source-specific context must be
|
|
@@ -137,6 +151,8 @@ export function buildSessionRecord({ opts, route, presetObj, surface, prompt, me
|
|
|
137
151
|
selectedContextWindow: opts.selectedContextWindow || null,
|
|
138
152
|
agent: opts.agent,
|
|
139
153
|
owner: opts.owner || 'user',
|
|
154
|
+
// 'agent' | 'coding' (session/agent-mode.mjs), resolved at creation.
|
|
155
|
+
sessionMode: opts.sessionMode,
|
|
140
156
|
bp3CoreContext: prompt.sessionMarkerCore,
|
|
141
157
|
promptIdentity: prompt.promptIdentity,
|
|
142
158
|
callerDisallowedTools: [...(opts.callerDisallowedTools ?? opts.disallowedTools ?? [])],
|
|
@@ -22,8 +22,9 @@ import { ROUTE_TOOL_ORDER } from '../../runtime-core/tool-catalog-data.mjs';
|
|
|
22
22
|
// the sort overhead on ~30 tools is negligible.
|
|
23
23
|
function _getMcpTools(mcpScopeId = null, cwd = null) {
|
|
24
24
|
// Project scope: servers limited to other project roots stay connected
|
|
25
|
-
// but leave this session's schema (session-runtime/extension-scopes).
|
|
26
|
-
|
|
25
|
+
// but leave this session's schema (session-runtime/extension-scopes). An
|
|
26
|
+
// agent's connectors apply at dispatch, never here.
|
|
27
|
+
const mcp = filterMcpToolsForSession(getMcpTools(mcpScopeId) || [], cwd, null);
|
|
27
28
|
// `public:false` tools stay registered in internal-tools for runtime
|
|
28
29
|
// rewrites/dispatch, but must never enter any model-visible schema (Lead
|
|
29
30
|
// full/mcp included). Filter before mapping because the projection below
|