mixdog 0.9.139 → 0.9.140
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/MIT.txt +8 -14
- package/NOTICE.md +66 -34
- package/package.json +1 -8
- package/src/lib/output-style-meta.cjs +115 -0
- package/src/lib/rules-builder.cjs +18 -100
- package/src/output-styles/common.md +27 -43
- package/src/output-styles/detailed.md +5 -5
- package/src/output-styles/extreme-minimal.md +7 -7
- package/src/output-styles/minimal.md +7 -6
- package/src/output-styles/simple.md +6 -5
- package/src/rules/lead/01-general.md +3 -0
- package/src/rules/shared/10-tool-workflow.md +2 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +3 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +4 -4
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/lossless-tool-output.test.mjs +6 -5
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +21 -0
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +7 -7
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +38 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +18 -3
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/edit-sequential-occupation.test.mjs +55 -0
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +27 -7
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.mjs +21 -2
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +62 -31
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.test.mjs +45 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +29 -2
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-client.mjs +5 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +9 -4
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +46 -1
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +11 -11
- package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +29 -2
- package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +7 -2
- package/src/runtime/agent/orchestrator/tools/patch/v4a-anchors.mjs +27 -0
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +6 -0
- package/src/runtime/agent/orchestrator/tools/patch-manifest.json +10 -10
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +72 -4
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +11 -11
- package/src/runtime/channels/lib/scheduler.mjs +1 -1
- package/src/runtime/media/download.mjs +1 -1
- package/src/runtime/media/jobs.mjs +9 -0
- package/src/runtime/media/store.mjs +4 -9
- package/src/runtime/memory/lib/embedding-worker.mjs +9 -4
- package/src/runtime/memory/lib/http-router.mjs +31 -0
- package/src/runtime/memory/lib/ko-morph.mjs +8 -1
- package/src/runtime/memory/lib/memory-cycle1.mjs +28 -2
- package/src/runtime/shared/background-tasks.mjs +1 -1
- package/src/runtime/shared/webhook-session-run.mjs +6 -0
- package/src/runtime/shared/webhook-session-run.test.mjs +14 -0
- package/src/session-runtime/context-status.mjs +4 -2
- package/src/session-runtime/cwd-tool-routing.test.mjs +56 -0
- package/src/session-runtime/lifecycle-api.mjs +47 -0
- package/src/session-runtime/output-styles.mjs +28 -83
- package/src/session-runtime/runtime-core.mjs +14 -3
- package/src/session-runtime/session-turn-api.mjs +26 -0
- package/src/session-runtime/tool-catalog.mjs +2 -2
- package/src/session-runtime/tool-defs.mjs +1 -1
- package/src/standalone/session-client.mjs +1 -1
- package/src/standalone/session-protocol.mjs +2 -0
- package/src/standalone/session-service.mjs +2 -2
- package/src/standalone/session-wire.mjs +1 -1
- package/src/tui/app/slash-commands.mjs +1 -0
- package/src/tui/app/slash-dispatch.mjs +18 -0
- package/src/tui/app/use-prompt-handlers.mjs +1 -1
- package/src/tui/app/use-transcript-window.mjs +1 -1
- package/src/tui/dist/index.mjs +59 -24
- package/src/tui/keyboard-protocol.mjs +1 -1
- package/src/tui/markdown/stream-fence.mjs +40 -17
- package/src/tui/session/labels.mjs +6 -1
- package/src/tui/session/session-api-ext.mjs +19 -0
- package/src/tui/session/session-api.mjs +1 -1
- package/src/tui/session/turn.mjs +20 -0
- package/src/tui/themes/light.mjs +4 -4
- package/src/tui/themes/teal.mjs +1 -1
- package/src/ui/statusline-segments.mjs +25 -6
- package/vendor/ink/build/_baseline-termio-keypress.js +240 -0
- package/vendor/ink/build/_baseline-termio-tokenize.js +253 -0
- package/vendor/ink/build/ink.js +3 -3
- package/vendor/ink/build/input-parser.js +1 -1
- package/vendor/ink/build/output.js +5 -5
- package/vendor/ink/build/termio-keypress.js +1 -1
- package/vendor/ink/build/termio-tokenize.js +160 -225
package/LICENSES/MIT.txt
CHANGED
|
@@ -8,24 +8,18 @@ component listed here. Each component keeps its own copyright notice.
|
|
|
8
8
|
https://github.com/microsoft/vscode
|
|
9
9
|
Copyright (c) 2015 - present Microsoft Corporation
|
|
10
10
|
|
|
11
|
+
Visual Studio Code Codicons (icon font; the icons are CC BY 4.0)
|
|
12
|
+
https://github.com/microsoft/vscode-codicons
|
|
13
|
+
Copyright (c) Microsoft Corporation
|
|
14
|
+
|
|
11
15
|
GitHub Pull Requests and Issues (VS Code extension)
|
|
12
16
|
https://github.com/microsoft/vscode-pull-request-github
|
|
13
17
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
OpenCode
|
|
20
|
-
https://github.com/anomalyco/opencode
|
|
21
|
-
Copyright (c) 2025 opencode
|
|
22
|
-
|
|
23
|
-
pi
|
|
24
|
-
https://github.com/earendil-works/pi
|
|
25
|
-
Copyright (c) 2025 Mario Zechner
|
|
26
|
-
|
|
27
|
-
Orca
|
|
28
|
-
Copyright (c) 2026 Lovecast Inc.
|
|
19
|
+
ripgrep (grep/ignore crates plus the packaged rg executable; offered as
|
|
20
|
+
MIT OR Unlicense — the MIT terms are taken here)
|
|
21
|
+
https://github.com/BurntSushi/ripgrep
|
|
22
|
+
Copyright (c) 2015 Andrew Gallant
|
|
29
23
|
|
|
30
24
|
Ink (vendored under vendor/ink, which keeps its own license file)
|
|
31
25
|
https://github.com/vadimdemedes/ink
|
package/NOTICE.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# NOTICE
|
|
2
2
|
|
|
3
|
-
Mixdog itself is MIT-licensed (see `LICENSE`).
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Mixdog itself is MIT-licensed (see `LICENSE`). The license sections below
|
|
4
|
+
cover third-party code and data that Mixdog actually carries. The closing
|
|
5
|
+
"Behavioral references" section records projects that only informed the
|
|
6
|
+
implementation, with no code taken. Everything is kept here in one place so
|
|
7
|
+
the individual source files stay free of scattered attribution comments.
|
|
7
8
|
|
|
8
9
|
Full license texts live in `LICENSES/`:
|
|
9
10
|
|
|
@@ -12,6 +13,10 @@ Full license texts live in `LICENSES/`:
|
|
|
12
13
|
- `LICENSES/Apache-2.0.txt` — the Apache License 2.0.
|
|
13
14
|
- `LICENSES/codex-NOTICE.txt` — the upstream NOTICE file of the Codex CLI,
|
|
14
15
|
carried forward as Apache-2.0 section 4(d) requires.
|
|
16
|
+
- `LICENSES/ripgrep-NOTICE.txt` — the ripgrep notice for the search crates
|
|
17
|
+
compiled into the native binaries.
|
|
18
|
+
- `LICENSES/editor-assets-NOTICE.txt` — the editor icon and language-data
|
|
19
|
+
notice referenced by the generated files.
|
|
15
20
|
|
|
16
21
|
## MIT
|
|
17
22
|
|
|
@@ -34,6 +39,14 @@ language contributions used to generate the Monaco pane languages.
|
|
|
34
39
|
`editor-ansi.ts` the terminal ANSI palette values, and `seti-icons.ts` /
|
|
35
40
|
`editor-languages.ts` are generated from the shipped extension data.
|
|
36
41
|
|
|
42
|
+
### Visual Studio Code Codicons — Copyright (c) Microsoft Corporation
|
|
43
|
+
|
|
44
|
+
<https://github.com/microsoft/vscode-codicons>
|
|
45
|
+
|
|
46
|
+
The chrome-level UI glyph font used by the desktop and web renderer. The code
|
|
47
|
+
is MIT; the icons themselves are licensed under Creative Commons Attribution
|
|
48
|
+
4.0 International (CC BY 4.0).
|
|
49
|
+
|
|
37
50
|
### GitHub Pull Requests extension — Copyright (c) Microsoft Corporation
|
|
38
51
|
|
|
39
52
|
<https://github.com/microsoft/vscode-pull-request-github>
|
|
@@ -46,39 +59,17 @@ The default pull-request query set and its category labels in
|
|
|
46
59
|
Bundled glyphs and colour tables. Full license text in
|
|
47
60
|
`apps/desktop/THIRD-PARTY-NOTICES.txt`.
|
|
48
61
|
|
|
49
|
-
###
|
|
50
|
-
|
|
51
|
-
<https://github.com/files-community/Files>
|
|
52
|
-
|
|
53
|
-
Folder-pane grouping keys, date-span labels, size buckets and the discrete
|
|
54
|
-
layout size ladder in `apps/desktop/src/renderer/FolderPane.lazy.tsx`.
|
|
55
|
-
|
|
56
|
-
### OpenCode — Copyright (c) Anomaly / SST
|
|
57
|
-
|
|
58
|
-
<https://github.com/anomalyco/opencode>
|
|
62
|
+
### ripgrep — Copyright (c) 2015 Andrew Gallant
|
|
59
63
|
|
|
60
|
-
|
|
61
|
-
streaming-markdown projection model.
|
|
64
|
+
<https://github.com/BurntSushi/ripgrep>
|
|
62
65
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
The `grep` and `ignore` library crates are compiled into the native search
|
|
67
|
+
binary, and the packaged `rg` executable ships as the grep tool's fast path.
|
|
68
|
+
ripgrep is offered under the MIT License OR the Unlicense; Mixdog takes the
|
|
69
|
+
MIT terms. The upstream notice is preserved as `LICENSES/ripgrep-NOTICE.txt`.
|
|
66
70
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<https://github.com/earendil-works/pi>
|
|
70
|
-
|
|
71
|
-
`trimPartialClosingFences()` in `src/tui/markdown/stream-fence.mjs`, ported
|
|
72
|
-
from the TUI markdown component.
|
|
73
|
-
|
|
74
|
-
### Orca — Copyright (c) 2026 Lovecast Inc.
|
|
75
|
-
|
|
76
|
-
Editor-surface and tab-hierarchy structure, the terminal host portal, the
|
|
77
|
-
keep-awake power-save blocker and the hosted-review link derivation.
|
|
78
|
-
|
|
79
|
-
- `apps/desktop/src/renderer/EditorPane.lazy.tsx`, `PaneSurfaceGate.tsx`,
|
|
80
|
-
`PullRequestsPane.tsx`, `SourceControlDock.tsx`
|
|
81
|
-
- `apps/desktop/src/main/agent-awake.ts`
|
|
71
|
+
- `native/mixdog-graph/` (the `grep` and `ignore` crates)
|
|
72
|
+
- `src/runtime/agent/orchestrator/tools/builtin/` (the `rg` fast path)
|
|
82
73
|
|
|
83
74
|
### Ink — Copyright (c) Vadim Demedes
|
|
84
75
|
|
|
@@ -107,3 +98,44 @@ upstream NOTICE file is preserved as `LICENSES/codex-NOTICE.txt`.
|
|
|
107
98
|
The Apache-2.0 terms require this notice to travel with any redistribution of
|
|
108
99
|
the derived files. Full license text: `LICENSES/Apache-2.0.txt`
|
|
109
100
|
(<https://www.apache.org/licenses/LICENSE-2.0>).
|
|
101
|
+
|
|
102
|
+
## Behavioral references
|
|
103
|
+
|
|
104
|
+
The projects below informed Mixdog through publicly observable behavior, a
|
|
105
|
+
published wire contract, or a documented algorithm. No source code from them
|
|
106
|
+
is present in Mixdog, so no license obligation travels with the result; they
|
|
107
|
+
are recorded here because the source files themselves carry no attribution
|
|
108
|
+
comments.
|
|
109
|
+
|
|
110
|
+
- **Chromium** — the workspace tab strip follows Chromium's tab-strip layout
|
|
111
|
+
semantics: two layout domains around the crossover width, the active-tab
|
|
112
|
+
floor, the inactive sliver floor, the left-to-right remainder grant and the
|
|
113
|
+
icon visibility ladder. The implementation is independent TypeScript and CSS
|
|
114
|
+
on Mixdog's own constants (`apps/desktop/src/renderer/WorkspaceTabStrip.tsx`,
|
|
115
|
+
`apps/desktop/src/renderer/desktop/04-workspace-tabs.css`).
|
|
116
|
+
- **GitHub Desktop** — the Source Control dock grammar: commit-form layout,
|
|
117
|
+
changed-file status glyph semantics, single-sentence path colouring, history
|
|
118
|
+
context-menu gating, and detached-checkout / tag rules. Painted entirely on
|
|
119
|
+
Mixdog's own semantic tokens.
|
|
120
|
+
- **OpenCode** — transcript auto-scroll gesture grammar, virtual-timeline
|
|
121
|
+
anchoring and the streaming-markdown projection model.
|
|
122
|
+
- **Orca** — editor-surface and tab-hierarchy structure, the terminal host
|
|
123
|
+
portal, the keep-awake power-save blocker and the hosted-review link
|
|
124
|
+
derivation.
|
|
125
|
+
- **Files** — the folder pane's grouping keys, date-span labels, size buckets
|
|
126
|
+
and discrete layout size ladder
|
|
127
|
+
(`apps/desktop/src/renderer/FolderPane.lazy.tsx`).
|
|
128
|
+
- **Claude Code** (Anthropic) — terminal input tokenizing and keypress
|
|
129
|
+
parsing, the TUI selection word model in `vendor/ink`, and interactive turn
|
|
130
|
+
semantics such as queued-message recall, message-selector rewind and
|
|
131
|
+
background-task lifetime. The Anthropic OAuth route additionally sends the
|
|
132
|
+
client identity that Anthropic's token edge validates; those values are a
|
|
133
|
+
wire requirement, not a derivation.
|
|
134
|
+
- **opencode-antigravity-auth** — MIT
|
|
135
|
+
(<https://github.com/NoeFabris/opencode-antigravity-auth>). The Google Cloud
|
|
136
|
+
Code Assist wire contract used by the Antigravity OAuth provider: OAuth
|
|
137
|
+
client parameters, endpoint fallback order, client impersonation headers,
|
|
138
|
+
request envelope and thinking-signature handling.
|
|
139
|
+
- **assistant-ui, Chatbox, Cherry Studio, Jan, Zed** — the heading-size and
|
|
140
|
+
list-density survey behind the desktop markdown ladder in
|
|
141
|
+
`apps/desktop/src/renderer/desktop/22-markdown.css`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mixdog",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.140",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Standalone mixdog coding-agent CLI/TUI workspace.",
|
|
@@ -108,7 +108,6 @@
|
|
|
108
108
|
"chalk": "^5.6.2",
|
|
109
109
|
"cli-highlight": "^2.1.11",
|
|
110
110
|
"diff": "^9.0.0",
|
|
111
|
-
"discord.js": "^14.26.4",
|
|
112
111
|
"ink": "^7.1.0",
|
|
113
112
|
"jsdom": "^27.0.0",
|
|
114
113
|
"kiwi-nlp": "^0.21.0",
|
|
@@ -129,12 +128,6 @@
|
|
|
129
128
|
"zod": "^3.25.76"
|
|
130
129
|
},
|
|
131
130
|
"overrides": {
|
|
132
|
-
"discord.js": {
|
|
133
|
-
"undici": "6.28.0"
|
|
134
|
-
},
|
|
135
|
-
"@discordjs/rest": {
|
|
136
|
-
"undici": "6.28.0"
|
|
137
|
-
},
|
|
138
131
|
"onnxruntime-node": {
|
|
139
132
|
"global-agent": "^4.1.3"
|
|
140
133
|
},
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// Output-style metadata contract: id normalization, frontmatter parsing,
|
|
2
|
+
// catalog ordering, and lookup. Required by the CJS rules builder (prompt
|
|
3
|
+
// injection) and imported by the ESM session runtime (pickers, config), so one
|
|
4
|
+
// schema governs both instead of two parallel copies drifting apart.
|
|
5
|
+
//
|
|
6
|
+
// Frontmatter schema for `output-styles/<id>.md`:
|
|
7
|
+
// name — canonical id (defaults to the file name)
|
|
8
|
+
// title | label — display label (defaults to a title-cased id)
|
|
9
|
+
// description — one-line picker text
|
|
10
|
+
// aliases — comma-separated alternate ids; the only alias source
|
|
11
|
+
// partial — true hides the file from the selectable catalog
|
|
12
|
+
// keep-shared-format — false replaces common.md instead of extending it
|
|
13
|
+
'use strict';
|
|
14
|
+
|
|
15
|
+
const DEFAULT_OUTPUT_STYLE_ID = 'simple';
|
|
16
|
+
// Catalog order: deepest first, then unknown/custom styles by label.
|
|
17
|
+
const OUTPUT_STYLE_ORDER = ['detailed', 'simple', 'minimal', 'extreme-minimal'];
|
|
18
|
+
|
|
19
|
+
/** Slug form of a style id. Aliases live in frontmatter, never in code. */
|
|
20
|
+
function normalizeOutputStyleId(value) {
|
|
21
|
+
const slug = String(value ?? '').trim().toLowerCase()
|
|
22
|
+
.replace(/[_\s]+/g, '-')
|
|
23
|
+
.replace(/^-+|-+$/g, '');
|
|
24
|
+
return /^[a-z0-9.-]+$/.test(slug) ? slug : '';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Separator-insensitive key so `one-line`, `one_line`, and `oneline` match. */
|
|
28
|
+
function outputStyleCompactKey(value) {
|
|
29
|
+
return normalizeOutputStyleId(value).replace(/[_.-]+/g, '');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function titleCaseOutputStyle(id) {
|
|
33
|
+
return String(id || '')
|
|
34
|
+
.split(/[_.-]+/)
|
|
35
|
+
.filter(Boolean)
|
|
36
|
+
.map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`)
|
|
37
|
+
.join(' ') || 'Default';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function parseOutputStyleFrontmatter(markdown) {
|
|
41
|
+
const match = String(markdown || '').match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
42
|
+
const meta = {};
|
|
43
|
+
if (!match) return meta;
|
|
44
|
+
for (const line of match[1].split(/\r?\n/)) {
|
|
45
|
+
const kv = line.match(/^([A-Za-z0-9_-]+):\s*(.*?)\s*$/);
|
|
46
|
+
if (!kv) continue;
|
|
47
|
+
meta[kv[1]] = kv[2].replace(/^['"]|['"]$/g, '').trim();
|
|
48
|
+
}
|
|
49
|
+
return meta;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function outputStyleFlag(value, fallback) {
|
|
53
|
+
const raw = String(value ?? '').trim().toLowerCase();
|
|
54
|
+
if (!raw) return fallback;
|
|
55
|
+
if (/^(?:true|1|yes|on)$/.test(raw)) return true;
|
|
56
|
+
if (/^(?:false|0|no|off)$/.test(raw)) return false;
|
|
57
|
+
return fallback;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Frontmatter → catalog entry. Returns null for `partial: true` files (the
|
|
62
|
+
* shared format partial) and for files with no usable id.
|
|
63
|
+
*/
|
|
64
|
+
function outputStyleMetaFromMarkdown(markdown, fileName) {
|
|
65
|
+
const meta = parseOutputStyleFrontmatter(markdown);
|
|
66
|
+
if (outputStyleFlag(meta.partial, false)) return null;
|
|
67
|
+
const fileId = normalizeOutputStyleId(String(fileName || '').replace(/\.md$/i, ''));
|
|
68
|
+
const id = normalizeOutputStyleId(meta.name) || fileId;
|
|
69
|
+
if (!id) return null;
|
|
70
|
+
return {
|
|
71
|
+
id,
|
|
72
|
+
label: String(meta.title || meta.label || '').trim() || titleCaseOutputStyle(id),
|
|
73
|
+
description: String(meta.description || '').trim(),
|
|
74
|
+
aliases: String(meta.aliases || '').split(',')
|
|
75
|
+
.map((alias) => normalizeOutputStyleId(alias))
|
|
76
|
+
.filter(Boolean),
|
|
77
|
+
// Built-in and custom styles both inherit the shared format partial; a
|
|
78
|
+
// style opts out only by declaring `keep-shared-format: false`.
|
|
79
|
+
keepSharedFormat: outputStyleFlag(meta['keep-shared-format'], true),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function sortOutputStyles(styles) {
|
|
84
|
+
return [...(styles || [])].sort((a, b) => {
|
|
85
|
+
const ai = OUTPUT_STYLE_ORDER.indexOf(a.id);
|
|
86
|
+
const bi = OUTPUT_STYLE_ORDER.indexOf(b.id);
|
|
87
|
+
if (ai !== bi) return (ai < 0 ? 999 : ai) - (bi < 0 ? 999 : bi);
|
|
88
|
+
return a.label.localeCompare(b.label, 'en', { sensitivity: 'base' });
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Resolve an id, label, or frontmatter alias, ignoring separators and case. */
|
|
93
|
+
function matchOutputStyle(value, styles) {
|
|
94
|
+
const id = normalizeOutputStyleId(value);
|
|
95
|
+
const compact = outputStyleCompactKey(value);
|
|
96
|
+
if (!id && !compact) return null;
|
|
97
|
+
return (styles || []).find((style) => {
|
|
98
|
+
if (style.id === id || outputStyleCompactKey(style.id) === compact) return true;
|
|
99
|
+
if (outputStyleCompactKey(style.label) === compact) return true;
|
|
100
|
+
return (style.aliases || []).some((alias) => alias === id || outputStyleCompactKey(alias) === compact);
|
|
101
|
+
}) || null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = {
|
|
105
|
+
DEFAULT_OUTPUT_STYLE_ID,
|
|
106
|
+
OUTPUT_STYLE_ORDER,
|
|
107
|
+
normalizeOutputStyleId,
|
|
108
|
+
outputStyleCompactKey,
|
|
109
|
+
titleCaseOutputStyle,
|
|
110
|
+
parseOutputStyleFrontmatter,
|
|
111
|
+
outputStyleFlag,
|
|
112
|
+
outputStyleMetaFromMarkdown,
|
|
113
|
+
sortOutputStyles,
|
|
114
|
+
matchOutputStyle,
|
|
115
|
+
};
|
|
@@ -35,6 +35,12 @@
|
|
|
35
35
|
|
|
36
36
|
const fs = require('fs');
|
|
37
37
|
const path = require('path');
|
|
38
|
+
const {
|
|
39
|
+
DEFAULT_OUTPUT_STYLE_ID,
|
|
40
|
+
matchOutputStyle,
|
|
41
|
+
outputStyleMetaFromMarkdown,
|
|
42
|
+
sortOutputStyles,
|
|
43
|
+
} = require('./output-style-meta.cjs');
|
|
38
44
|
|
|
39
45
|
/**
|
|
40
46
|
* Read a single section from mixdog-config.json (unified config).
|
|
@@ -187,6 +193,7 @@ function buildLanguageSection(dataDir) {
|
|
|
187
193
|
const lines = [
|
|
188
194
|
`- Default user-facing language${source}: ${language.prompt}. Use it for all user-facing text (preambles, progress, questions, reports, notices), overriding output style; switch only when the user does or asks.`,
|
|
189
195
|
`- Keep code identifiers, paths, commands, symbols, API names, and exact errors in original form.`,
|
|
196
|
+
`- Never coin a word-for-word translation of source jargon; use the established original term or a plain functional description.`,
|
|
190
197
|
];
|
|
191
198
|
return `# Language\n\n${lines.join('\n')}`;
|
|
192
199
|
}
|
|
@@ -221,84 +228,10 @@ function omitToolRoutes(text, omitTools = []) {
|
|
|
221
228
|
return out.replace(/[ \t]+\n/g, '\n').replace(/\n{3,}/g, '\n\n');
|
|
222
229
|
}
|
|
223
230
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
['extremesimple', 'extreme-minimal'],
|
|
229
|
-
['extreme-simple', 'extreme-minimal'],
|
|
230
|
-
['extreme_simple', 'extreme-minimal'],
|
|
231
|
-
['extrememinimal', 'extreme-minimal'],
|
|
232
|
-
['extreme_minimal', 'extreme-minimal'],
|
|
233
|
-
['mono', 'extreme-minimal'],
|
|
234
|
-
['oneline', 'extreme-minimal'],
|
|
235
|
-
['one-line', 'extreme-minimal'],
|
|
236
|
-
['one_line', 'extreme-minimal'],
|
|
237
|
-
]);
|
|
238
|
-
|
|
239
|
-
function normalizeOutputStyleId(value) {
|
|
240
|
-
const raw = String(value || '').trim().toLowerCase();
|
|
241
|
-
if (!raw) return '';
|
|
242
|
-
const slug = raw.replace(/[_\s]+/g, '-').replace(/^-+|-+$/g, '');
|
|
243
|
-
const compact = slug.replace(/[_.-]+/g, '');
|
|
244
|
-
if (OUTPUT_STYLE_ALIASES.has(slug)) return OUTPUT_STYLE_ALIASES.get(slug);
|
|
245
|
-
if (OUTPUT_STYLE_ALIASES.has(compact)) return OUTPUT_STYLE_ALIASES.get(compact);
|
|
246
|
-
return /^[a-z0-9.-]+$/.test(slug) ? slug : '';
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
function outputStyleCompactKey(value) {
|
|
250
|
-
return normalizeOutputStyleId(value).replace(/[_.-]+/g, '');
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function titleCaseOutputStyle(id) {
|
|
254
|
-
return String(id || '')
|
|
255
|
-
.split(/[_.-]+/)
|
|
256
|
-
.filter(Boolean)
|
|
257
|
-
.map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`)
|
|
258
|
-
.join(' ') || 'Default';
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
function parseOutputStyleFrontmatter(markdown) {
|
|
262
|
-
const match = String(markdown || '').match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
263
|
-
const meta = {};
|
|
264
|
-
if (!match) return meta;
|
|
265
|
-
for (const line of match[1].split(/\r?\n/)) {
|
|
266
|
-
const kv = line.match(/^([A-Za-z0-9_-]+):\s*(.*?)\s*$/);
|
|
267
|
-
if (!kv) continue;
|
|
268
|
-
meta[kv[1]] = kv[2].replace(/^['"]|['"]$/g, '').trim();
|
|
269
|
-
}
|
|
270
|
-
return meta;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
function outputStyleFlag(value, fallback) {
|
|
274
|
-
const raw = String(value ?? '').trim().toLowerCase();
|
|
275
|
-
if (!raw) return fallback;
|
|
276
|
-
if (/^(?:true|1|yes|on)$/.test(raw)) return true;
|
|
277
|
-
if (/^(?:false|0|no|off)$/.test(raw)) return false;
|
|
278
|
-
return fallback;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
function readOutputStyleEntry(filePath, source) {
|
|
282
|
-
const raw = readOptional(filePath);
|
|
283
|
-
if (!raw) return null;
|
|
284
|
-
const meta = parseOutputStyleFrontmatter(raw);
|
|
285
|
-
if (/^(?:true|1|yes)$/i.test(String(meta.partial || '').trim())) return null;
|
|
286
|
-
const fileId = normalizeOutputStyleId(path.basename(filePath).replace(/\.md$/i, ''));
|
|
287
|
-
const id = normalizeOutputStyleId(meta.name) || fileId;
|
|
288
|
-
if (!id) return null;
|
|
289
|
-
return {
|
|
290
|
-
id,
|
|
291
|
-
label: String(meta.title || meta.label || '').trim() || titleCaseOutputStyle(id),
|
|
292
|
-
aliases: String(meta.aliases || '').split(',')
|
|
293
|
-
.map((alias) => normalizeOutputStyleId(alias))
|
|
294
|
-
.filter(Boolean),
|
|
295
|
-
// Built-in and custom styles both inherit the shared format partial; a
|
|
296
|
-
// style opts out only by declaring `keep-shared-format: false`.
|
|
297
|
-
keepSharedFormat: outputStyleFlag(meta['keep-shared-format'], true),
|
|
298
|
-
source,
|
|
299
|
-
raw,
|
|
300
|
-
};
|
|
301
|
-
}
|
|
231
|
+
// Framing line under the style header: the block owns user-facing prose only,
|
|
232
|
+
// so a style (including a `keep-shared-format: false` replacement) never reads
|
|
233
|
+
// as guidance for code or tool payloads.
|
|
234
|
+
const OUTPUT_STYLE_ANCHOR = 'The section below governs how you write user-facing text; it outranks any other formatting habit and does not apply to code or tool calls.';
|
|
302
235
|
|
|
303
236
|
function listOutputStyleEntries({ PLUGIN_ROOT, DATA_DIR }) {
|
|
304
237
|
const byId = new Map();
|
|
@@ -309,27 +242,12 @@ function listOutputStyleEntries({ PLUGIN_ROOT, DATA_DIR }) {
|
|
|
309
242
|
let files = [];
|
|
310
243
|
try { files = fs.readdirSync(dir).filter((name) => name.toLowerCase().endsWith('.md')).sort(); } catch {}
|
|
311
244
|
for (const name of files) {
|
|
312
|
-
const
|
|
313
|
-
|
|
245
|
+
const raw = readOptional(path.join(dir, name));
|
|
246
|
+
const meta = raw ? outputStyleMetaFromMarkdown(raw, name) : null;
|
|
247
|
+
if (meta) byId.set(meta.id, { ...meta, source, raw });
|
|
314
248
|
}
|
|
315
249
|
}
|
|
316
|
-
return [...byId.values()]
|
|
317
|
-
const ai = OUTPUT_STYLE_ORDER.indexOf(a.id);
|
|
318
|
-
const bi = OUTPUT_STYLE_ORDER.indexOf(b.id);
|
|
319
|
-
if (ai !== bi) return (ai < 0 ? 999 : ai) - (bi < 0 ? 999 : bi);
|
|
320
|
-
return a.label.localeCompare(b.label, 'en', { sensitivity: 'base' });
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
function findOutputStyleEntry(value, styles) {
|
|
325
|
-
const id = normalizeOutputStyleId(value);
|
|
326
|
-
const compact = outputStyleCompactKey(value);
|
|
327
|
-
if (!id && !compact) return null;
|
|
328
|
-
return styles.find((style) => {
|
|
329
|
-
if (style.id === id || outputStyleCompactKey(style.id) === compact) return true;
|
|
330
|
-
if (outputStyleCompactKey(style.label) === compact) return true;
|
|
331
|
-
return style.aliases.some((alias) => alias === id || outputStyleCompactKey(alias) === compact);
|
|
332
|
-
}) || null;
|
|
250
|
+
return sortOutputStyles([...byId.values()]);
|
|
333
251
|
}
|
|
334
252
|
|
|
335
253
|
/** Shared format partial: a user copy in DATA_DIR overrides the built-in one. */
|
|
@@ -343,14 +261,14 @@ function loadOutputStyle({ PLUGIN_ROOT, DATA_DIR }) {
|
|
|
343
261
|
// `agent.outputStyle` key is dropped by config canonicalization.
|
|
344
262
|
const configured = String(readUnifiedConfig(DATA_DIR).outputStyle || '').trim() || DEFAULT_OUTPUT_STYLE_ID;
|
|
345
263
|
const styles = listOutputStyleEntries({ PLUGIN_ROOT, DATA_DIR });
|
|
346
|
-
const style =
|
|
347
|
-
||
|
|
264
|
+
const style = matchOutputStyle(configured, styles)
|
|
265
|
+
|| matchOutputStyle(DEFAULT_OUTPUT_STYLE_ID, styles)
|
|
348
266
|
|| styles[0];
|
|
349
267
|
if (!style) return '';
|
|
350
268
|
const selected = stripFrontmatter(style.raw);
|
|
351
269
|
if (!selected) return '';
|
|
352
270
|
const common = style.keepSharedFormat ? readSharedFormatPartial({ PLUGIN_ROOT, DATA_DIR }) : '';
|
|
353
|
-
return [`# Output Style: ${style.label}`, common, selected].filter(Boolean).join('\n\n');
|
|
271
|
+
return [`# Output Style: ${style.label}`, OUTPUT_STYLE_ANCHOR, common, selected].filter(Boolean).join('\n\n');
|
|
354
272
|
}
|
|
355
273
|
|
|
356
274
|
function buildSharedToolContent({ PLUGIN_ROOT, omitTools = [] } = {}) {
|
|
@@ -7,48 +7,32 @@ partial: true
|
|
|
7
7
|
|
|
8
8
|
## Shared Output Format
|
|
9
9
|
|
|
10
|
-
- Lead with the answer or action
|
|
11
|
-
|
|
12
|
-
sentences
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
from question type
|
|
10
|
+
- Lead with the answer or action, then the context needed to understand it, then
|
|
11
|
+
lower-priority detail. Write for a person, not a console log: complete
|
|
12
|
+
sentences, explained terms, and a register matched to the reader's language,
|
|
13
|
+
tone, and apparent expertise.
|
|
14
|
+
- Select content by the active depth variation before formatting it. Formatting
|
|
15
|
+
never restores information that variation discarded.
|
|
16
|
+
- Choose the shape from the content and the reader. Markdown is available, not
|
|
17
|
+
mandatory; prose, bullets, numbered steps, headings, tables, and code may
|
|
18
|
+
combine in any way that makes this particular answer easier to read, and no
|
|
19
|
+
response shape is a default or a required mapping from question type.
|
|
20
20
|
- Output renders as GitHub-flavored Markdown — tables, task lists, footnotes,
|
|
21
21
|
fenced code with a language tag, and `$$…$$` math — in a proportional-width
|
|
22
|
-
surface
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
- Use an inverted pyramid when useful: answer first, then the context needed to
|
|
40
|
-
understand it, then lower-priority detail. State each material point once; do
|
|
41
|
-
not repeat the opening conclusion in a `Summary`, `Conclusion`, or `In short`
|
|
42
|
-
ending, and never force a recurring response template.
|
|
43
|
-
- Keep established facts separate from plausible inference. Do not invent a
|
|
44
|
-
mechanism, value, consequence, or certainty to make an explanation feel
|
|
45
|
-
complete.
|
|
46
|
-
- Use user-facing terms without unexplained internal shorthand, routine process
|
|
47
|
-
narration, raw output dumps, or emojis unless requested. Show code and file
|
|
48
|
-
references only when their exact form helps the reader.
|
|
49
|
-
- Reader understanding outranks terseness, but every retained sentence must earn
|
|
50
|
-
its place. Do not restate the request or announce compliance with constraints
|
|
51
|
-
such as language or tool use. Remove preamble, filler, obvious statements, and
|
|
52
|
-
repetition. Once every requested point is covered, stop; do not append a recap,
|
|
53
|
-
solution, recommendation, next step, or offer of more help unless requested or
|
|
54
|
-
necessary to prevent a misleading answer. Preserve exact technical literals.
|
|
22
|
+
surface, so space-aligned columns and ASCII art never line up; use a real table
|
|
23
|
+
or a fenced block instead. Use tables only for short enumerable or quantitative
|
|
24
|
+
facts, and keep explanatory reasoning outside the cells.
|
|
25
|
+
- Keep simple answers visually simple and add structure only where it creates
|
|
26
|
+
useful grouping, order, or contrast. Never produce an essay-shaped wall of
|
|
27
|
+
text, and never overcorrect into fragments, decorative emphasis, tiny headings,
|
|
28
|
+
needless nesting, or a recurring template.
|
|
29
|
+
- Give each paragraph or list item one idea and keep the flow linear, so the
|
|
30
|
+
reader builds meaning forward without re-parsing what came before.
|
|
31
|
+
- Keep established facts separate from plausible inference. Never invent a
|
|
32
|
+
mechanism, value, or certainty to make an explanation feel complete, preserve
|
|
33
|
+
exact technical literals, and show code or file references only where their
|
|
34
|
+
exact form helps.
|
|
35
|
+
- State each material point once and stop when the request is covered. Do not
|
|
36
|
+
restate the request, close with a recap, or append an unrequested
|
|
37
|
+
recommendation, next step, or offer of help; no emojis, raw output dumps, or
|
|
38
|
+
narration of your own process unless asked.
|
|
@@ -9,8 +9,8 @@ aliases: verbose, full
|
|
|
9
9
|
|
|
10
10
|
Detailed — concrete explanation.
|
|
11
11
|
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
lessons
|
|
12
|
+
- Retain: the answer plus every established explanatory layer that materially
|
|
13
|
+
improves understanding — mechanism, evidence, trade-offs, implications, and
|
|
14
|
+
useful examples. Deepen the requested subject rather than widening it.
|
|
15
|
+
- Omit: speculation that fills an evidentiary gap, and any expansion into fixes,
|
|
16
|
+
recommendations, or adjacent lessons that were not requested.
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
name: extreme-minimal
|
|
3
3
|
title: Extreme Minimal
|
|
4
4
|
description: Final decision or direct answer in one or two sentences
|
|
5
|
-
aliases: extreme,
|
|
5
|
+
aliases: extreme, extreme-simple, one-line, mono
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
## Depth Variation
|
|
9
9
|
|
|
10
10
|
Extreme minimal — final decision or answer.
|
|
11
11
|
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
when asked to explain or report.
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
- Retain: only the final decision, result, or direct answer. For a cause
|
|
13
|
+
question, that is the highest-level cause, not its concrete causal chain.
|
|
14
|
+
- Omit: every heading, label, list, explanation, supporting fact, scope, caveat,
|
|
15
|
+
recap, and follow-up, even when asked to explain or report.
|
|
16
|
+
- Shape: one or two short sentences. Never pack discarded detail into a longer
|
|
17
|
+
sentence.
|
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
name: minimal
|
|
3
3
|
title: Minimal
|
|
4
4
|
description: Conclusion, core cause, and one decisive fact
|
|
5
|
+
aliases: brief, short
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
## Depth Variation
|
|
8
9
|
|
|
9
10
|
Minimal — conclusion and core cause.
|
|
10
11
|
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
- Retain: the conclusion, the single core cause that determines it, one or two
|
|
13
|
+
decisive concrete facts that make the cause clear, and the immediate
|
|
14
|
+
consequence when it completes the answer. Stop before a full explanation.
|
|
15
|
+
- Omit: secondary evidence, deployment state, unaffected scope, broader impact,
|
|
16
|
+
exceptions, remediation, and process, unless that category is the requested
|
|
17
|
+
answer.
|
|
@@ -9,9 +9,10 @@ aliases: default, concise, handoff
|
|
|
9
9
|
|
|
10
10
|
Simple — concise summary.
|
|
11
11
|
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
explanation over compression that makes the reader infer a missing
|
|
16
|
-
|
|
12
|
+
- Retain: the main answer, the essential causal sequence, the strongest
|
|
13
|
+
supporting evidence, direct consequences, and any material scope or caveat.
|
|
14
|
+
Preserve enough context for the answer to stand on its own, and prefer a
|
|
15
|
+
complete explanation over compression that makes the reader infer a missing
|
|
16
|
+
step.
|
|
17
|
+
- Omit: secondary evidence, exhaustive implementation detail, examples, edge
|
|
17
18
|
cases, adjacent implications, alternatives, and unrequested remediation.
|
|
@@ -11,4 +11,7 @@
|
|
|
11
11
|
recoverability.
|
|
12
12
|
- Mid-task: replacement supersedes; addition folds in; status gets a brief
|
|
13
13
|
answer while work continues. After compaction, resume the summary.
|
|
14
|
+
- Auto-compact owns context management: never propose stopping work to the
|
|
15
|
+
user and never stop on your own judgment; resume and continue the work
|
|
16
|
+
after every compaction.
|
|
14
17
|
- Final text ends the turn only when done.
|
|
@@ -18,3 +18,5 @@
|
|
|
18
18
|
- Treat failure as new evidence and repeat steps 1–4 only for affected facets.
|
|
19
19
|
Report a blocker when no deterministic next action remains.
|
|
20
20
|
- Use only named tools present in the current tool surface.
|
|
21
|
+
- Deferred tools auto-load on a direct call; when their exact arguments are
|
|
22
|
+
not visible, call `load_tool` first and read the surfaced schema.
|