mixdog 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -6
- package/package.json +1 -2
- package/scripts/latest-guard.mjs +63 -0
- package/scripts/lib/run-node-tests.mjs +103 -27
- package/scripts/lib/test-failure-summary.mjs +7 -2
- package/scripts/merge-mac-update-feed.mjs +107 -0
- package/scripts/mobile-release.mjs +210 -0
- package/scripts/post-release-check.mjs +353 -0
- package/scripts/publish-asset-release.mjs +43 -0
- package/scripts/release-guard.mjs +63 -0
- package/scripts/release-paths.mjs +39 -2
- package/scripts/test.mjs +29 -7
- package/src/defaults/shipped-history.json +2 -0
- package/src/defaults/skills/computer-use/SKILL.md +1 -1
- package/src/defaults/skills/setup/references/actions.md +1 -0
- package/src/headless-role.mjs +2 -2
- package/src/lib/keychain-cjs.cjs +582 -17
- package/src/lib/rules-builder.cjs +0 -23
- package/src/rules/lead/LEAD.md +2 -2
- package/src/runtime/agent/orchestrator/config-storage.mjs +32 -4
- package/src/runtime/agent/orchestrator/config.mjs +18 -0
- package/src/runtime/agent/orchestrator/context/instruction-files.mjs +130 -0
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/lib/open-login-url.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +254 -0
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +218 -0
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-tokens.mjs +239 -0
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +233 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth-login.mjs +247 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth-tokens.mjs +225 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +542 -0
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +25 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/openai-codex-model.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +14 -6
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog-store.mjs +99 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +4 -8
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +2 -7
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +1 -5
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +12 -14
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +11 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-call-ids.mjs +90 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +19 -11
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +28 -0
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +1 -5
- package/src/runtime/agent/orchestrator/session/read-dedup.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/turn-effort.mjs +18 -0
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +11 -8
- package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +9 -4
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/bashism-rewrite.mjs +245 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +13 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +49 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +9 -7
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +61 -8
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +28 -3
- package/src/runtime/agent/orchestrator/tools/builtin/path-utils.mjs +73 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +17 -6
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +23 -5
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +93 -43
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +32 -6
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +9 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +12 -15
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +124 -91
- package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +19 -4
- package/src/runtime/channels/index.mjs +1 -5
- package/src/runtime/channels/lib/runtime-paths.mjs +8 -23
- package/src/runtime/channels/lib/tool-dispatch.mjs +1 -13
- package/src/runtime/channels/lib/worker-ipc.mjs +2 -2
- package/src/runtime/channels/lib/worker-main.mjs +4 -34
- package/src/runtime/computer-bridge/client.mjs +25 -1
- package/src/runtime/computer-bridge/linux-action-capabilities.mjs +84 -0
- package/src/runtime/computer-bridge/linux-readiness.d.mts +52 -0
- package/src/runtime/computer-bridge/linux-readiness.mjs +411 -0
- package/src/runtime/computer-bridge/test-linux-display.mjs +5 -0
- package/src/runtime/effort-judge/compact-tokenizer.mjs +13 -8
- package/src/runtime/effort-judge/judge-input.mjs +5 -2
- package/src/runtime/effort-judge/model-install.mjs +9 -3
- package/src/runtime/effort-judge/model-manifest.json +7 -7
- package/src/runtime/memory/lib/embedding-worker.mjs +9 -3
- package/src/runtime/memory/lib/pg/supervisor.mjs +3 -0
- package/src/runtime/shared/config.mjs +50 -2
- package/src/runtime/shared/developer-options.mjs +7 -0
- package/src/runtime/shared/instruction-files-mode.mjs +9 -0
- package/src/runtime/shared/llm/model-catalog.mjs +2 -1
- package/src/runtime/shared/llm/openai-daybreak.mjs +79 -0
- package/src/runtime/shared/pristine-execution-contract.json +9 -0
- package/src/runtime/shared/pristine-execution.mjs +1 -1
- package/src/runtime/shared/provider-accounts.mjs +2 -0
- package/src/runtime/shared/resource-admission.mjs +10 -3
- package/src/runtime/shared/schedule-model-ref.mjs +11 -0
- package/src/runtime/shared/semver.d.mts +1 -0
- package/src/runtime/shared/semver.mjs +57 -0
- package/src/runtime/shared/session-approval-wait.mjs +35 -0
- package/src/runtime/shared/shell-display.mjs +4 -2
- package/src/runtime/shared/tool-surface.mjs +2 -2
- package/src/runtime/shared/turn-worktree-snapshot.mjs +11 -10
- package/src/runtime/shared/update-checker.mjs +2 -31
- package/src/session-runtime/boot/apis.mjs +5 -0
- package/src/session-runtime/boot/begin.mjs +0 -2
- package/src/session-runtime/boot/tools.mjs +5 -4
- package/src/session-runtime/model-recency.mjs +3 -0
- package/src/session-runtime/provider-auth/login.mjs +10 -10
- package/src/session-runtime/provider-auth/setup.mjs +22 -2
- package/src/session-runtime/provider-models/row-hydration.mjs +12 -4
- package/src/session-runtime/provider-readiness.mjs +4 -0
- package/src/session-runtime/resource-mcp-api.mjs +7 -3
- package/src/session-runtime/runtime-bootstrap.mjs +0 -4
- package/src/session-runtime/runtime-facade.mjs +5 -0
- package/src/session-runtime/runtime-paths.mjs +0 -1
- package/src/session-runtime/schedule-session-run.mjs +3 -1
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +55 -14
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +15 -3
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +2 -0
- package/src/session-runtime/services/agent-tool/worker-index/approval-wait.mjs +97 -0
- package/src/session-runtime/services/agent-tool/worker-index/mutation-batch.mjs +4 -2
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -2
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +3 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +58 -2
- package/src/session-runtime/services/agent-tool/worker-index.mjs +69 -15
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +2 -0
- package/src/session-runtime/services/channel-admin.mjs +4 -2
- package/src/session-runtime/services/channel-worker.mjs +1 -1
- package/src/session-runtime/services/provider-admin.mjs +80 -17
- package/src/session-runtime/services/seeds.mjs +7 -10
- package/src/session-runtime/services/usage-dashboard-model.mjs +6 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +15 -0
- package/src/session-runtime/settings-profile-api.mjs +27 -2
- package/src/session-runtime/setup-tool/executor.mjs +5 -0
- package/src/session-runtime/setup-tool/tool-defs.mjs +8 -0
- package/src/session-runtime/starter-guide-state.mjs +62 -0
- package/src/session-runtime/tool-policy-refresh.mjs +3 -0
- package/src/session-runtime/webhook-session-run.mjs +3 -1
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -2
- package/src/standalone/channel-binding.mjs +1 -2
- package/src/standalone/channel-transport/call-dispatch.mjs +4 -10
- package/src/standalone/daemon-channels-loader.mjs +2 -3
- package/src/standalone/local-session-runtime.mjs +2 -78
- package/src/standalone/session-protocol.mjs +2 -0
- package/src/tui/app/model-options.mjs +13 -1
- package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +10 -4
- package/src/tui/app/provider-setup/oauth-actions.mjs +5 -0
- package/src/tui/dist/index.mjs +84 -34
- package/src/tui/session/context-state.mjs +2 -0
- package/src/tui/session/live-share/owner.mjs +17 -0
- package/src/tui/session/oauth-flows.mjs +2 -0
- package/src/tui/session/session-api/extensions.mjs +12 -8
- package/src/tui/session/session-api/integrations.mjs +9 -8
- package/src/tui/session/session-api/routes.mjs +2 -2
- package/src/tui/session/session-api/settings.mjs +1 -0
- package/src/tui/session/session-api/shared.mjs +10 -6
- package/src/tui/session/tool-card-results/grouped-result.mjs +11 -2
- package/src/tui/session/transcript-spill/spill-dir.mjs +22 -6
- package/src/tui/spinner-meta.mjs +26 -10
- package/src/runtime/channels/tool-defs.mjs +0 -17
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* openai-oauth-catalog-store.mjs — where the openai-oauth model catalog is
|
|
3
|
+
* cached, and the catalog's own route successors.
|
|
4
|
+
*
|
|
5
|
+
* Kept free of the provider runtime so config load can read the last fetched
|
|
6
|
+
* catalog synchronously: a saved route on a model the catalog has superseded
|
|
7
|
+
* moves to the model the catalog names for it.
|
|
8
|
+
*/
|
|
9
|
+
import { makeModelCache } from './model-cache.mjs';
|
|
10
|
+
import { accessProgramModelParameters, accessProgramOnly } from '../../../shared/llm/openai-daybreak.mjs';
|
|
11
|
+
import { formatScheduleModelRef, parseScheduleModelRef } from '../../../shared/schedule-model-ref.mjs';
|
|
12
|
+
|
|
13
|
+
export const CODEX_MODEL_CACHE_OPTIONS = Object.freeze({
|
|
14
|
+
fileName: 'openai-oauth-models.json',
|
|
15
|
+
ttlMs: 24 * 60 * 60_000,
|
|
16
|
+
version: 6,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export const CODEX_PROVIDER_ID = 'openai-oauth';
|
|
20
|
+
|
|
21
|
+
let snapshotCache = null;
|
|
22
|
+
|
|
23
|
+
/** The last saved catalog, stale or not; null when none was ever fetched. */
|
|
24
|
+
function savedCatalog() {
|
|
25
|
+
snapshotCache ||= makeModelCache(CODEX_MODEL_CACHE_OPTIONS);
|
|
26
|
+
return snapshotCache.loadSync({ allowStale: true });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The route a model moves to, read off the catalog alone; null when it stays.
|
|
31
|
+
* - A standalone access-program variant (its access programs omit the
|
|
32
|
+
* standard one) moves to the first listed regular model, by catalog
|
|
33
|
+
* priority, that accepts the same program, with that program's toggle on.
|
|
34
|
+
* - A model whose `upgrade.retirement_at` has passed moves to `upgrade.model`.
|
|
35
|
+
* Returns { model, modelParameters? }.
|
|
36
|
+
*/
|
|
37
|
+
export function codexModelSuccessor(models, modelId, now = Date.now()) {
|
|
38
|
+
if (!Array.isArray(models) || !modelId) return null;
|
|
39
|
+
const entry = models.find((model) => model?.id === modelId);
|
|
40
|
+
if (!entry) return null;
|
|
41
|
+
const program = accessProgramOnly(entry);
|
|
42
|
+
if (program) {
|
|
43
|
+
const modelParameters = accessProgramModelParameters(program);
|
|
44
|
+
if (!modelParameters) return null;
|
|
45
|
+
const target = models
|
|
46
|
+
.filter(
|
|
47
|
+
(model) =>
|
|
48
|
+
model?.id &&
|
|
49
|
+
model.id !== modelId &&
|
|
50
|
+
model.hidden !== true &&
|
|
51
|
+
!accessProgramOnly(model) &&
|
|
52
|
+
Array.isArray(model.accessPrograms) &&
|
|
53
|
+
model.accessPrograms.includes(program)
|
|
54
|
+
)
|
|
55
|
+
.sort((a, b) => (a.priority ?? Infinity) - (b.priority ?? Infinity))[0];
|
|
56
|
+
return target ? { model: target.id, modelParameters } : null;
|
|
57
|
+
}
|
|
58
|
+
const upgrade = entry.upgrade;
|
|
59
|
+
const retiresAt = Date.parse(upgrade?.retirementAt || '');
|
|
60
|
+
if (upgrade?.model && Number.isFinite(retiresAt) && retiresAt <= now) return { model: upgrade.model };
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** A saved openai-oauth route moved to its catalog successor; any other route unchanged. */
|
|
65
|
+
export function migrateCodexRoute(route, models = savedCatalog()) {
|
|
66
|
+
if (String(route?.provider || '').trim() !== CODEX_PROVIDER_ID) return route;
|
|
67
|
+
const successor = codexModelSuccessor(models, String(route.model || '').trim());
|
|
68
|
+
if (!successor) return route;
|
|
69
|
+
const current =
|
|
70
|
+
route.modelParameters && typeof route.modelParameters === 'object' && !Array.isArray(route.modelParameters)
|
|
71
|
+
? route.modelParameters
|
|
72
|
+
: {};
|
|
73
|
+
return {
|
|
74
|
+
...route,
|
|
75
|
+
model: successor.model,
|
|
76
|
+
...(successor.modelParameters || Object.hasOwn(route, 'modelParameters')
|
|
77
|
+
? { modelParameters: { ...current, ...(successor.modelParameters || {}) } }
|
|
78
|
+
: {}),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** A stored schedule/webhook model ref ("provider/model@effort+fast?k=v") moved
|
|
83
|
+
* to its catalog successor; preset names and current models unchanged. */
|
|
84
|
+
export function migrateCodexModelRef(ref, models = savedCatalog()) {
|
|
85
|
+
const route = parseScheduleModelRef(ref);
|
|
86
|
+
if (!route || typeof route !== 'object') return ref;
|
|
87
|
+
const migrated = migrateCodexRoute(route, models);
|
|
88
|
+
return migrated === route ? ref : formatScheduleModelRef(migrated);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** `modelSettings` keys whose model the catalog has superseded (they apply to nothing any more). */
|
|
92
|
+
export function supersededCodexSettingsKey(key, models = savedCatalog()) {
|
|
93
|
+
const prefix = `${CODEX_PROVIDER_ID}/`;
|
|
94
|
+
return key.startsWith(prefix) && Boolean(codexModelSuccessor(models, key.slice(prefix.length)));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function loadSavedCodexCatalog() {
|
|
98
|
+
return savedCatalog();
|
|
99
|
+
}
|
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
* levels, visibility), so the catalog is normalized and enriched once here and
|
|
9
9
|
* every consumer reads the same records.
|
|
10
10
|
*
|
|
11
|
-
* openai-oauth.mjs re-exports
|
|
12
|
-
* resolve unchanged.
|
|
11
|
+
* openai-oauth.mjs re-exports these lookups as its facade.
|
|
13
12
|
*/
|
|
14
13
|
import { makeModelCache } from './model-cache.mjs';
|
|
14
|
+
import { CODEX_MODEL_CACHE_OPTIONS } from './openai-oauth-catalog-store.mjs';
|
|
15
15
|
import { enrichModels } from './model-catalog.mjs';
|
|
16
16
|
import { sanitizeModelList } from './model-list-sanitize.mjs';
|
|
17
17
|
import { modelSupportsServiceTier } from './model-service-tiers.mjs';
|
|
@@ -21,8 +21,6 @@ import { getLlmDispatcher } from '../../../shared/llm/http-agent.mjs';
|
|
|
21
21
|
import { CODEX_OAUTH_ORIGINATOR, codexModelsUrl } from './openai-codex-endpoints.mjs';
|
|
22
22
|
import { _normalizeCodexModel, _markLatestCodex } from './openai-codex-model.mjs';
|
|
23
23
|
|
|
24
|
-
const CODEX_MODEL_CACHE_TTL_MS = 24 * 60 * 60_000;
|
|
25
|
-
const CODEX_MODEL_CACHE_SCHEMA_VERSION = 6;
|
|
26
24
|
const CATALOG_FETCH_TIMEOUT_MS = 10_000;
|
|
27
25
|
|
|
28
26
|
// In-memory mirror of the on-disk catalog, same pattern as anthropic-oauth.
|
|
@@ -31,9 +29,7 @@ let _mirror = null;
|
|
|
31
29
|
let _refreshInFlight = null;
|
|
32
30
|
|
|
33
31
|
const _modelCache = makeModelCache({
|
|
34
|
-
|
|
35
|
-
ttlMs: CODEX_MODEL_CACHE_TTL_MS,
|
|
36
|
-
version: CODEX_MODEL_CACHE_SCHEMA_VERSION,
|
|
32
|
+
...CODEX_MODEL_CACHE_OPTIONS,
|
|
37
33
|
onSave: (models) => {
|
|
38
34
|
_mirror = Array.isArray(models) ? models.slice() : null;
|
|
39
35
|
},
|
|
@@ -96,7 +92,7 @@ export function resolveLatestCodexModel() {
|
|
|
96
92
|
if (!Array.isArray(_mirror)) return null;
|
|
97
93
|
let best = null;
|
|
98
94
|
for (const m of _mirror) {
|
|
99
|
-
if (!m?.id || m.visibility === 'hide' || !Number.isFinite(m.priority)) continue;
|
|
95
|
+
if (!m?.id || m.visibility === 'hide' || m.hidden === true || !Number.isFinite(m.priority)) continue;
|
|
100
96
|
if (!best || m.priority < best.priority) best = m;
|
|
101
97
|
}
|
|
102
98
|
return best?.id || null;
|
|
@@ -12,6 +12,7 @@ import { createServer } from 'node:http';
|
|
|
12
12
|
import { randomBytes } from 'node:crypto';
|
|
13
13
|
import { createOAuthPkce, parseOAuthCodeInput } from './lib/oauth-pkce.mjs';
|
|
14
14
|
import { OAUTH_PAGE_CONTENT_TYPE, oauthSuccessHtml } from './lib/oauth-page.mjs';
|
|
15
|
+
import { openLoginUrl } from './lib/open-login-url.mjs';
|
|
15
16
|
|
|
16
17
|
const TOKEN_URL = 'https://auth.openai.com/oauth/token';
|
|
17
18
|
const AUTHORIZE_URL = 'https://auth.openai.com/oauth/authorize';
|
|
@@ -141,13 +142,7 @@ export function createOpenAIOAuthLogin(deps) {
|
|
|
141
142
|
process.stderr.write(
|
|
142
143
|
`\n[openai-oauth] Open this URL to log in to ChatGPT (OpenAI OAuth):\n${url.toString()}\n\n`
|
|
143
144
|
);
|
|
144
|
-
if (
|
|
145
|
-
try {
|
|
146
|
-
const { openInBrowser } = await import('../../../shared/open-url.mjs');
|
|
147
|
-
openInBrowser(url.toString());
|
|
148
|
-
} catch (err) {
|
|
149
|
-
process.stderr.write(`[openai-oauth] browser open failed: ${String(err?.message || err).slice(0, 200)}\n`);
|
|
150
|
-
}
|
|
145
|
+
if (openBrowser) await openLoginUrl('openai-oauth', url.toString());
|
|
151
146
|
});
|
|
152
147
|
server.on('error', (err) =>
|
|
153
148
|
finish(
|
|
@@ -7,6 +7,7 @@ import { isResponsesFreeformTool, toResponsesCustomTool } from './custom-tool-wi
|
|
|
7
7
|
import { _envFlag } from './openai-oauth-http-sse.mjs';
|
|
8
8
|
import { findCachedCodexModel } from './openai-oauth-catalog.mjs';
|
|
9
9
|
import { resolveOpenAiServiceTier } from './openai-service-tier.mjs';
|
|
10
|
+
import { daybreakAccessPrograms } from '../../../shared/llm/openai-daybreak.mjs';
|
|
10
11
|
|
|
11
12
|
export function toOpenAIResponsesTool(t) {
|
|
12
13
|
if (t?.name === 'load_tool' || t?.name === 'tool_search') {
|
|
@@ -219,6 +220,12 @@ export function buildRequestBody(messages, model, tools, sendOpts) {
|
|
|
219
220
|
toolChoice,
|
|
220
221
|
});
|
|
221
222
|
const verbosity = requestedVerbosity(opts);
|
|
223
|
+
// Daybreak Blue rides on the ChatGPT route only, and only for a model that
|
|
224
|
+
// accepts it; the server still decides entitlement.
|
|
225
|
+
const accessPrograms =
|
|
226
|
+
promptCacheProvider === 'openai-oauth'
|
|
227
|
+
? daybreakAccessPrograms(findCachedCodexModel(model) || model, opts.modelParameters)
|
|
228
|
+
: null;
|
|
222
229
|
// Match the request body shape the OAuth backend expects so the
|
|
223
230
|
// server-side auto-cache routes correctly: text.verbosity / include /
|
|
224
231
|
// tool_choice / parallel_tool_calls are inert for most callers but their
|
|
@@ -246,6 +253,7 @@ export function buildRequestBody(messages, model, tools, sendOpts) {
|
|
|
246
253
|
...(serviceTier ? { service_tier: serviceTier } : {}),
|
|
247
254
|
prompt_cache_key: promptCacheKey,
|
|
248
255
|
text: { verbosity },
|
|
256
|
+
...(accessPrograms ? { access_programs: accessPrograms } : {}),
|
|
249
257
|
...(maxOutputTokens ? { max_output_tokens: maxOutputTokens } : {}),
|
|
250
258
|
};
|
|
251
259
|
}
|
|
@@ -26,6 +26,8 @@ const OAUTH_PROVIDER_NAMES = new Set([
|
|
|
26
26
|
'anthropic-oauth',
|
|
27
27
|
'openai-oauth',
|
|
28
28
|
'grok-oauth',
|
|
29
|
+
'muse-code-oauth',
|
|
30
|
+
'mimo-oauth',
|
|
29
31
|
'cursor-oauth',
|
|
30
32
|
'antigravity-oauth',
|
|
31
33
|
]);
|
|
@@ -143,6 +145,8 @@ const PROVIDER_MODULES = {
|
|
|
143
145
|
'openai-oauth': ['./openai-oauth.mjs', 'OpenAIOAuthProvider'],
|
|
144
146
|
'anthropic-oauth': ['./anthropic-oauth.mjs', 'AnthropicOAuthProvider'],
|
|
145
147
|
'grok-oauth': ['./grok-oauth.mjs', 'GrokOAuthProvider'],
|
|
148
|
+
'muse-code-oauth': ['./muse-code-oauth.mjs', 'MuseCodeOAuthProvider'],
|
|
149
|
+
'mimo-oauth': ['./mimo-oauth.mjs', 'MimoOAuthProvider'],
|
|
146
150
|
'cursor-oauth': ['./cursor.mjs', 'CursorOAuthProvider'],
|
|
147
151
|
'antigravity-oauth': ['./antigravity-oauth.mjs', 'AntigravityOAuthProvider'],
|
|
148
152
|
'cursor-api': ['./cursor.mjs', 'CursorApiProvider'],
|
|
@@ -25,6 +25,8 @@ const EFFORT_OPTIONS_BY_PROVIDER = {
|
|
|
25
25
|
// xAI Grok 4.6+: low/medium/high/xhigh. Reasoning cannot be disabled.
|
|
26
26
|
xai: ['low', 'medium', 'high', 'xhigh'],
|
|
27
27
|
'grok-oauth': ['low', 'medium', 'high', 'xhigh'],
|
|
28
|
+
'muse-code-oauth': ['minimal', 'low', 'medium', 'high', 'xhigh'],
|
|
29
|
+
'mimo-oauth': ['minimal', 'low', 'medium', 'high'],
|
|
28
30
|
// Antigravity carries the effort tier inside the wire model id
|
|
29
31
|
// (gemini-3-pro-high / -low, claude-*-thinking), so the route exposes none.
|
|
30
32
|
'antigravity-oauth': [],
|
|
@@ -129,7 +129,21 @@ export function validateGoalToolCall(value) {
|
|
|
129
129
|
if (!action) throw new Error('goal action is required');
|
|
130
130
|
if (!ACTION_FIELDS[action]) throw new Error(`goal action must be one of: ${Object.keys(ACTION_FIELDS).join(', ')}`);
|
|
131
131
|
const extras = Object.keys(value).filter((key) => !TOOL_FIELDS.has(key));
|
|
132
|
-
if (extras.length)
|
|
132
|
+
if (extras.length) {
|
|
133
|
+
throw new Error(
|
|
134
|
+
`goal arguments contain unknown fields: ${extras.join(', ')}. Allowed for ${action}: ${ACTION_FIELDS[action].join(', ')}`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
// A JSON-stringified tasks/updates array is the same list; parse it in place.
|
|
138
|
+
for (const key of ['tasks', 'updates']) {
|
|
139
|
+
if (typeof value[key] !== 'string' || !value[key].trim().startsWith('[')) continue;
|
|
140
|
+
try {
|
|
141
|
+
const parsed = JSON.parse(value[key]);
|
|
142
|
+
if (Array.isArray(parsed)) value[key] = parsed;
|
|
143
|
+
} catch {
|
|
144
|
+
/* left as-is for the handler's own rejection */
|
|
145
|
+
}
|
|
146
|
+
}
|
|
133
147
|
// Restored providers can fill every optional field. Consume only the active
|
|
134
148
|
// action's payload; an absent/empty revision keeps old frozen schemas usable.
|
|
135
149
|
if (ACTION_FIELDS[action].includes('revision') && value.revision != null && value.revision !== '') {
|
|
@@ -98,8 +98,7 @@ const admitted = (tools, names) => (tools || []).filter((tool) => names.includes
|
|
|
98
98
|
|
|
99
99
|
/**
|
|
100
100
|
* Assemble this runtime's tool definitions from the loaded tool-def modules.
|
|
101
|
-
* Pure: callers resolve their own availability flags (skills env gate
|
|
102
|
-
* ownership) and pass the already-built goal/agent tool arrays.
|
|
101
|
+
* Pure: callers resolve their own availability flags (skills env gate) and pass the already-built goal/agent tool arrays.
|
|
103
102
|
*
|
|
104
103
|
* - `standaloneTools` is the model-facing set (also the deferred catalog base).
|
|
105
104
|
* - `internalToolDefs` adds the `public: false` web-search tools: reachable
|
|
@@ -108,7 +107,6 @@ const admitted = (tools, names) => (tools || []).filter((tool) => names.includes
|
|
|
108
107
|
export function collectStandaloneToolDefs({
|
|
109
108
|
webSearchToolDefs,
|
|
110
109
|
memoryToolDefs,
|
|
111
|
-
channelToolDefs,
|
|
112
110
|
codeGraphToolDefs,
|
|
113
111
|
browserToolDefs = [],
|
|
114
112
|
computerToolDefs = [],
|
|
@@ -119,7 +117,6 @@ export function collectStandaloneToolDefs({
|
|
|
119
117
|
setupToolDefs = [],
|
|
120
118
|
goalTools = [],
|
|
121
119
|
agentTools = [],
|
|
122
|
-
isChannelTool = () => false,
|
|
123
120
|
skillToolEnabled = true,
|
|
124
121
|
}) {
|
|
125
122
|
const webSearchRuntimeTools = admitted(webSearchToolDefs?.TOOL_DEFS, WEB_SEARCH_RUNTIME_TOOLS);
|
|
@@ -129,7 +126,6 @@ export function collectStandaloneToolDefs({
|
|
|
129
126
|
CWD_TOOL,
|
|
130
127
|
...webSearchRuntimeTools.filter((tool) => tool?.public !== false),
|
|
131
128
|
...admitted(memoryToolDefs?.TOOL_DEFS, MEMORY_RUNTIME_TOOLS),
|
|
132
|
-
...(channelToolDefs?.TOOL_DEFS || []).filter((tool) => isChannelTool(tool?.name)),
|
|
133
129
|
...admitted(codeGraphToolDefs?.CODE_GRAPH_TOOL_DEFS, CODE_GRAPH_RUNTIME_TOOLS),
|
|
134
130
|
...admitted(browserToolDefs, BROWSER_RUNTIME_TOOLS),
|
|
135
131
|
...admitted(computerToolDefs, COMPUTER_RUNTIME_TOOLS),
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { estimateTokens } from './token-estimate.mjs';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
beginIdentity,
|
|
5
|
+
endIdentity,
|
|
6
|
+
putJsonElement,
|
|
7
|
+
putJsonString,
|
|
8
|
+
putRaw,
|
|
9
|
+
putShapeText,
|
|
10
|
+
} from './context-identity-writer.mjs';
|
|
4
11
|
import { positiveInt } from '../../../shared/numbers.mjs';
|
|
5
12
|
import { hasPlainPrototype } from '../../../shared/object.mjs';
|
|
6
13
|
import { createContextFingerprinter } from './context-fingerprint.mjs';
|
|
@@ -39,19 +46,10 @@ export {
|
|
|
39
46
|
resolveSessionCompactPolicy,
|
|
40
47
|
} from './context-compaction-policy.mjs';
|
|
41
48
|
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
// provider reports for the previous request) and the heuristic only prices the
|
|
47
|
-
// delta appended since then. Measured across 5,552 real deltas the worst
|
|
48
|
-
// underestimate was 2,985 tokens (1.5% of a 200K window) with a +6.5%
|
|
49
|
-
// aggregate bias toward overcounting.
|
|
50
|
-
//
|
|
51
|
-
// providerTokenCalibration() below reconciles that estimate with actual
|
|
52
|
-
// billing at the provider-aware aggregation boundary (compaction pressure /
|
|
53
|
-
// context gauge), never inside the provider-agnostic per-message memo.
|
|
54
|
-
// ---------------------------------------------------------------------------
|
|
49
|
+
// providerTokenCalibration() below reconciles the ./token-estimate.mjs
|
|
50
|
+
// heuristic with actual billing at the provider-aware aggregation boundary
|
|
51
|
+
// (compaction pressure / context gauge), never inside the provider-agnostic
|
|
52
|
+
// per-message memo.
|
|
55
53
|
|
|
56
54
|
// Billed-prompt / estimate ratio per provider family. Env overrides let a
|
|
57
55
|
// deployment recalibrate without a code change; values are clamped to a
|
|
@@ -15,6 +15,7 @@ import { sendWithRecovery } from '../send-with-recovery.mjs';
|
|
|
15
15
|
import { stripInlineImages } from '../image-strip-recovery.mjs';
|
|
16
16
|
import { runWithProviderRequestToolsScope } from '../../runtime-core/provider-request-tools.mjs';
|
|
17
17
|
import { REPEAT_FAIL_LIMIT } from './loop-state.mjs';
|
|
18
|
+
import { createToolCallIdResolver } from './tool-call-ids.mjs';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Open an iteration: refresh the live cwd, drain queued steering after a
|
|
@@ -104,13 +105,22 @@ export async function beginIteration(state) {
|
|
|
104
105
|
getNextIteration: () => nextIteration,
|
|
105
106
|
repeatFailLimit: REPEAT_FAIL_LIMIT,
|
|
106
107
|
});
|
|
108
|
+
const resolveToolCallId = createToolCallIdResolver(messages);
|
|
107
109
|
opts.onToolCall = (call) => {
|
|
110
|
+
resolveToolCallId(call);
|
|
108
111
|
try {
|
|
109
112
|
opts.onAssistantToolCallObserved?.(call, { eagerStarted: false });
|
|
110
113
|
} catch {}
|
|
111
114
|
return eager.onToolCall(call);
|
|
112
115
|
};
|
|
113
|
-
return {
|
|
116
|
+
return {
|
|
117
|
+
iterT0,
|
|
118
|
+
nextIteration,
|
|
119
|
+
sendTools: boundary.sendTools,
|
|
120
|
+
requestToolScope: boundary.requestToolScope,
|
|
121
|
+
eager,
|
|
122
|
+
resolveToolCallId,
|
|
123
|
+
};
|
|
114
124
|
}
|
|
115
125
|
|
|
116
126
|
/** Project the transcript for the provider and send it with recovery. */
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tool-call-ids.mjs — a tool call id is unique within a transcript.
|
|
3
|
+
*
|
|
4
|
+
* Tool results are paired to their assistant turn by id, and the pairing
|
|
5
|
+
* repairs treat a second assistant turn that reuses an id as a duplicate
|
|
6
|
+
* with no result: they drop it, so its (already executed) result never
|
|
7
|
+
* reaches the model and the model asks again, forever. Local and
|
|
8
|
+
* OpenAI-compatible servers reuse ids across turns (`call_0`, `call_1`), so
|
|
9
|
+
* a call whose id the history already carries is renamed before anything —
|
|
10
|
+
* eager dispatch, the transcript, the UI — records it.
|
|
11
|
+
*/
|
|
12
|
+
import { collectAssistantToolCallIds } from '../context-tool-pairs.mjs';
|
|
13
|
+
|
|
14
|
+
function usedToolCallIds(messages) {
|
|
15
|
+
const used = new Set();
|
|
16
|
+
for (const message of messages) {
|
|
17
|
+
if (message?.role === 'tool' && message.toolCallId) used.add(message.toolCallId);
|
|
18
|
+
for (const id of collectAssistantToolCallIds(message)) used.add(id);
|
|
19
|
+
}
|
|
20
|
+
return used;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* One resolver per provider round. A call keeps its id unless the history, an
|
|
25
|
+
* id this round already handed out, or (for the final batch) another call of
|
|
26
|
+
* the batch holds it; then it gets the smallest free `<id>-<n>`.
|
|
27
|
+
*
|
|
28
|
+
* A call is seen twice per round: streamed (`resolve`, one at a time, often a
|
|
29
|
+
* clone) and in the final batch (`resolve.all`). The n-th call carrying an
|
|
30
|
+
* original id in the final batch is the n-th streamed one, so both resolve to
|
|
31
|
+
* the same new id while two distinct calls that share an id stay distinct.
|
|
32
|
+
* Mutates and returns the calls.
|
|
33
|
+
*/
|
|
34
|
+
export function createToolCallIdResolver(messages) {
|
|
35
|
+
const handedOut = new Set();
|
|
36
|
+
const byCall = new WeakMap();
|
|
37
|
+
const byOriginal = new Map();
|
|
38
|
+
|
|
39
|
+
const isTaken = (id, reserved) => handedOut.has(id) || reserved.has(id) || usedToolCallIds(messages).has(id);
|
|
40
|
+
|
|
41
|
+
const allocate = (call, reserved) => {
|
|
42
|
+
const original = call.id;
|
|
43
|
+
let id = original;
|
|
44
|
+
if (isTaken(id, new Set())) {
|
|
45
|
+
let n = 2;
|
|
46
|
+
while (isTaken(`${original}-${n}`, reserved)) n += 1;
|
|
47
|
+
id = `${original}-${n}`;
|
|
48
|
+
}
|
|
49
|
+
handedOut.add(id);
|
|
50
|
+
if (!byOriginal.has(original)) byOriginal.set(original, []);
|
|
51
|
+
byOriginal.get(original).push(id);
|
|
52
|
+
byCall.set(call, { original, id });
|
|
53
|
+
call.id = id;
|
|
54
|
+
return call;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const resolve = (call) => {
|
|
58
|
+
if (!call?.id) return call;
|
|
59
|
+
const known = byCall.get(call);
|
|
60
|
+
if (known) {
|
|
61
|
+
call.id = known.id;
|
|
62
|
+
return call;
|
|
63
|
+
}
|
|
64
|
+
return allocate(call, new Set());
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
resolve.all = (calls) => {
|
|
68
|
+
const seen = new Map();
|
|
69
|
+
const originals = calls.map((call) => byCall.get(call)?.original ?? call?.id);
|
|
70
|
+
calls.forEach((call, index) => {
|
|
71
|
+
if (!call?.id) return;
|
|
72
|
+
const original = originals[index];
|
|
73
|
+
const nth = seen.get(original) ?? 0;
|
|
74
|
+
seen.set(original, nth + 1);
|
|
75
|
+
const known = byCall.get(call) ?? null;
|
|
76
|
+
const mapped = known?.id ?? byOriginal.get(original)?.[nth];
|
|
77
|
+
if (mapped) {
|
|
78
|
+
call.id = mapped;
|
|
79
|
+
if (!known) byCall.set(call, { original, id: mapped });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Ids later in the batch that no earlier pass has placed yet stay theirs.
|
|
83
|
+
const reserved = new Set(originals.slice(index + 1).filter(Boolean));
|
|
84
|
+
allocate(call, reserved);
|
|
85
|
+
});
|
|
86
|
+
return calls;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
return resolve;
|
|
90
|
+
}
|
|
@@ -4,22 +4,30 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { resolvePreToolAskApproval } from '../tool-helpers.mjs';
|
|
6
6
|
import { runAbortable, throwIfAborted } from '../../../../../shared/abort-race.mjs';
|
|
7
|
+
import { beginSessionApprovalWait } from '../../manager/runtime-liveness.mjs';
|
|
7
8
|
|
|
8
9
|
const isArgsObject = (value) => value && typeof value === 'object' && !Array.isArray(value);
|
|
9
10
|
|
|
10
11
|
async function askApproval(call, { callerSessionId, executeOpts, toolApprovalHook, decision }) {
|
|
11
12
|
const askReason = String(decision?.reason || 'approval requested by hook').trim();
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
// While the user decides, the session is waiting on them, not working.
|
|
14
|
+
const releaseApprovalWait = beginSessionApprovalWait(callerSessionId);
|
|
15
|
+
let askOutcome;
|
|
16
|
+
try {
|
|
17
|
+
askOutcome = await runAbortable(executeOpts.signal, () =>
|
|
18
|
+
resolvePreToolAskApproval({
|
|
19
|
+
toolName: call.name,
|
|
20
|
+
args: call.args,
|
|
21
|
+
cwd: call.cwd,
|
|
22
|
+
sessionId: callerSessionId,
|
|
23
|
+
toolCallId: executeOpts.toolCallId || null,
|
|
24
|
+
askReason,
|
|
25
|
+
toolApprovalHook,
|
|
26
|
+
})
|
|
27
|
+
);
|
|
28
|
+
} finally {
|
|
29
|
+
releaseApprovalWait();
|
|
30
|
+
}
|
|
23
31
|
if (askOutcome.denial) return { denial: askOutcome.denial };
|
|
24
32
|
const approval = askOutcome.approval;
|
|
25
33
|
if (approval && typeof approval === 'object' && isArgsObject(approval.args)) call.args = approval.args;
|
|
@@ -18,6 +18,7 @@ export async function runToolPhase(state, round, sent, onToolCall) {
|
|
|
18
18
|
const { opts, messages, tools, sessionId, sessionRef, signal, response, suppressMidTurnText } = state;
|
|
19
19
|
state.noToolTurn.noteToolCallTurn();
|
|
20
20
|
const calls = response.toolCalls;
|
|
21
|
+
round.resolveToolCallId.all(calls);
|
|
21
22
|
state.toolCallsTotal += calls.length;
|
|
22
23
|
// Surface any mid-turn assistant text (preamble before a tool call) to the
|
|
23
24
|
// UI. Providers that stream via onTextDelta already rendered it; providers
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
// closed?: boolean, // flipped by closeSession()
|
|
20
20
|
// }
|
|
21
21
|
import { createAbortController } from '../../../../shared/abort-controller.mjs';
|
|
22
|
+
import { emitSessionApprovalWaitChange } from '../../../../shared/session-approval-wait.mjs';
|
|
22
23
|
import { publishHeartbeat, deleteHeartbeat } from '../store.mjs';
|
|
23
24
|
import { DEFAULT_ACTIVITY_HEARTBEAT_MS } from '../../stall-policy.mjs';
|
|
24
25
|
import { finishBrowserTurn } from '../../../../browser-bridge/client.mjs';
|
|
@@ -286,6 +287,32 @@ export function markSessionToolOutputTail(id, tail) {
|
|
|
286
287
|
entry.toolOutputTail = text ? text.slice(-4000) : null;
|
|
287
288
|
entry.toolOutputTailAt = Date.now();
|
|
288
289
|
}
|
|
290
|
+
// A turn blocked on the user: a PreToolUse `ask` waiting for the tool
|
|
291
|
+
// approval only the user can give. Published as `awaitingUser: 'approval'` so
|
|
292
|
+
// status surfaces stop presenting the session as working. Counted, because one
|
|
293
|
+
// tool batch can hold several approvals at once; the field clears when the
|
|
294
|
+
// last one settles. Never creates an entry — a real turn always has one.
|
|
295
|
+
// Returns the release, which is idempotent.
|
|
296
|
+
export function beginSessionApprovalWait(id) {
|
|
297
|
+
const entry = id ? _runtimeState.get(id) : null;
|
|
298
|
+
if (!entry) return () => {};
|
|
299
|
+
entry.approvalWaits = (entry.approvalWaits || 0) + 1;
|
|
300
|
+
entry.awaitingUser = 'approval';
|
|
301
|
+
// The waiting turn: the end transition carries the begin's turn even when
|
|
302
|
+
// the turn has settled (askStartedAt cleared) by the time it releases.
|
|
303
|
+
const meta = { turnAt: entry.askStartedAt || 0 };
|
|
304
|
+
// Only the begin/end transitions are announced (the worker index persists them).
|
|
305
|
+
if (entry.approvalWaits === 1) emitSessionApprovalWaitChange(id, 'approval', meta);
|
|
306
|
+
let released = false;
|
|
307
|
+
return () => {
|
|
308
|
+
if (released) return;
|
|
309
|
+
released = true;
|
|
310
|
+
entry.approvalWaits = Math.max(0, (entry.approvalWaits || 0) - 1);
|
|
311
|
+
if (entry.approvalWaits > 0) return;
|
|
312
|
+
entry.awaitingUser = null;
|
|
313
|
+
emitSessionApprovalWaitChange(id, null, meta);
|
|
314
|
+
};
|
|
315
|
+
}
|
|
289
316
|
// Parent AbortSignal listeners are dropped on askSession unwind (finally /
|
|
290
317
|
// terminal return) and on error/cancel/close — not in markSessionDone, which
|
|
291
318
|
// also runs between queued follow-up turns within one ask.
|
|
@@ -411,6 +438,7 @@ export function getSessionProgressSnapshot(sessionId) {
|
|
|
411
438
|
),
|
|
412
439
|
waitingForTransport,
|
|
413
440
|
waitingForFirstSemantic,
|
|
441
|
+
...(entry.awaitingUser ? { awaitingUser: entry.awaitingUser } : {}),
|
|
414
442
|
};
|
|
415
443
|
}
|
|
416
444
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// the volatile environment block that closes them, and the seed messages that
|
|
4
4
|
// carry all four to the provider with their cache tiers.
|
|
5
5
|
import { buildSkillManifest, composeSystemPrompt } from '../../context/collect.mjs';
|
|
6
|
+
import { configuredInstructionFilesMode, loadInstructionFilesContext } from '../../context/instruction-files.mjs';
|
|
6
7
|
import {
|
|
7
8
|
_buildBaseRules,
|
|
8
9
|
_buildAgentRules,
|
|
@@ -97,6 +98,12 @@ export function composeSessionSystem(opts, { profile, providerName, modelName, s
|
|
|
97
98
|
// as [session, bp3EnvironmentContext], so the language block must
|
|
98
99
|
// already sit at the end of this string to stay last after a refresh.
|
|
99
100
|
const environmentTailContext = [shellEnvironmentContext, languageContext].filter(Boolean).join('\n\n---\n\n');
|
|
101
|
+
// User instruction files (AGENTS.md / CLAUDE.md, global then the project
|
|
102
|
+
// root's); a tool-free role and a profile skipping `claudemd` get none.
|
|
103
|
+
const instructionFilesContext =
|
|
104
|
+
toolFreeRole || profile?.skip?.claudemd
|
|
105
|
+
? ''
|
|
106
|
+
: loadInstructionFilesContext({ mode: configuredInstructionFilesMode(), cwd: opts.cwd });
|
|
100
107
|
const composed = composeSystemPrompt({
|
|
101
108
|
userPrompt: opts.systemPrompt,
|
|
102
109
|
agentRules: injectedRules || undefined,
|
|
@@ -108,6 +115,7 @@ export function composeSessionSystem(opts, { profile, providerName, modelName, s
|
|
|
108
115
|
agent: resolvedAgent,
|
|
109
116
|
workflowContext: opts.workflowContext || null,
|
|
110
117
|
coreMemoryContext: opts.coreMemoryContext || null,
|
|
118
|
+
instructionFilesContext: instructionFilesContext || null,
|
|
111
119
|
skillManifest: buildSkillManifest(skills),
|
|
112
120
|
environmentContext: shellEnvironmentContext,
|
|
113
121
|
provider: providerName || null,
|
|
@@ -78,6 +78,9 @@ export function sessionOriginFields(opts, { profile, presetObj, providerCacheOpt
|
|
|
78
78
|
// Agent Runtime metadata — optional. Applied on every ask() to merge
|
|
79
79
|
// profile-driven cache settings into provider sendOpts.
|
|
80
80
|
profileId: profile?.id || null,
|
|
81
|
+
// A profile skipping `claudemd` keeps instruction files out of later
|
|
82
|
+
// empty-session prompt rebuilds too (tool-policy-refresh.mjs).
|
|
83
|
+
skipInstructionFiles: profile?.skip?.claudemd === true,
|
|
81
84
|
permissionMode: opts.permissionMode ?? null,
|
|
82
85
|
providerCacheOpts: providerCacheOpts || null,
|
|
83
86
|
parentSessionId: opts.parentSessionId || null,
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
// src/runtime/agent/orchestrator/session/manager.mjs
|
|
2
|
-
// Thin facade over the split session-manager modules in ./manager/.
|
|
3
|
-
// re-exports the EXACT public surface the previous monolith exposed so every
|
|
4
|
-
// importer (loop.mjs, loop/tool-exec.mjs, agent-dispatch.mjs, session-builder,
|
|
5
|
-
// abort-lookup, statusline-agents, headless-role, session-runtime, and the
|
|
6
|
-
// smoke scripts) keeps resolving its symbols through manager.mjs unchanged.
|
|
2
|
+
// Thin facade over the split session-manager modules in ./manager/.
|
|
7
3
|
//
|
|
8
4
|
// Module map:
|
|
9
5
|
// manager/runtime-liveness.mjs — in-memory stage/heartbeat + accessors
|
|
@@ -323,6 +323,9 @@ function projectChildWorkerRow(row, { now, heartbeatMtimes }) {
|
|
|
323
323
|
fast: row.fast === true || session?.fast === true,
|
|
324
324
|
status: declaredWorking && !working ? 'unknown' : declaredStatus,
|
|
325
325
|
stage: declaredWorking && !working ? 'unknown' : declaredStage,
|
|
326
|
+
// A live turn blocked on the user's approval (persisted by the agent
|
|
327
|
+
// tool's worker index); never carried by a row that is no longer working.
|
|
328
|
+
...(working && row.awaitingUser === 'approval' ? { awaitingUser: 'approval' } : {}),
|
|
326
329
|
startedAt: row.startedAt || row.createdAt || session?.createdAt || null,
|
|
327
330
|
turnStartedAt: working ? row.turnStartedAt || null : null,
|
|
328
331
|
createdAt: row.createdAt || session?.createdAt || null,
|
|
@@ -15,6 +15,7 @@ import { crossTurnSignature, isEditProgressTool } from '../loop/completion-guard
|
|
|
15
15
|
import { isEagerDispatchable, isToolCallDedupEligible, parseNativeToolSearchPayload } from '../loop/tool-helpers.mjs';
|
|
16
16
|
import { restoreToolCallBodyForId } from '../loop/stored-tool-args.mjs';
|
|
17
17
|
import { stageToolResult } from './state.mjs';
|
|
18
|
+
import { toolMetaPatchFromMessage } from '../transcript-restore/tool-result-status.mjs';
|
|
18
19
|
import {
|
|
19
20
|
compactToolResultImage,
|
|
20
21
|
resizeImageBuffer,
|
|
@@ -281,6 +282,7 @@ function completedToolResult(completed, result, postprocessStartedAt) {
|
|
|
281
282
|
toolTiming: toolTiming(completed, postprocessStartedAt),
|
|
282
283
|
...(completed.nativeToolSearch ? { nativeToolSearch: completed.nativeToolSearch } : {}),
|
|
283
284
|
...(uiDiff !== null ? { uiDiff } : {}),
|
|
285
|
+
...toolMetaPatchFromMessage(completed.result),
|
|
284
286
|
};
|
|
285
287
|
}
|
|
286
288
|
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
aggregateLoadingTargets,
|
|
24
24
|
aggregateRawResult,
|
|
25
25
|
aggregateResultPatch,
|
|
26
|
+
assignToolMetaFromMessage,
|
|
26
27
|
assignUiDiffFromMessage,
|
|
27
28
|
mergeAggregateCategoryEntries,
|
|
28
29
|
stringUiDiffPatch,
|
|
@@ -131,6 +132,7 @@ function attachRestoredToolResult(message, pendingByCallId) {
|
|
|
131
132
|
const text = (typeof message?.content === 'string' ? message.content : toolResultText(message?.content)) || '';
|
|
132
133
|
target.result = text;
|
|
133
134
|
assignUiDiffFromMessage(target, message);
|
|
135
|
+
assignToolMetaFromMessage(target, message);
|
|
134
136
|
// Cancel/crash control bodies are not red failures — show Cancelled tone.
|
|
135
137
|
if (toolResultTerminalStatus(text) === 'cancelled') {
|
|
136
138
|
target.isError = false;
|