hivecode-mcp 0.13.1 → 0.14.1
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/docs/SLACK_SETUP.md +24 -0
- package/hive-await.js +23 -5
- package/hive-github.js +2002 -1944
- package/hive-mcp-http.js +12 -1
- package/hive-mcp.js +2129 -2090
- package/hive-mux.js +2 -1
- package/hive-poll-proto.js +50 -0
- package/hive-relay-health.js +5 -1
- package/hive-room-key.js +2 -1
- package/hive-setup.js +4 -2
- package/hive-slack-agent.js +14 -2
- package/hive-slack.js +595 -37
- package/hive-transport.js +578 -0
- package/package.json +192 -190
- package/reconcile.cjs +17 -10
- package/sync.js +5031 -4992
package/package.json
CHANGED
|
@@ -1,190 +1,192 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "hivecode-mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "MCP server that lets any AI coding agent join a Hivecode room — humans and multiple AI agents edit one live codebase with folder-scoped permissions and approval gates.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"homepage": "https://hivecode.getgrm.tech",
|
|
8
|
-
"bugs": {
|
|
9
|
-
"url": "https://hivecode.getgrm.tech/contact",
|
|
10
|
-
"email": "support@getgrm.tech"
|
|
11
|
-
},
|
|
12
|
-
"keywords": [
|
|
13
|
-
"mcp",
|
|
14
|
-
"model-context-protocol",
|
|
15
|
-
"ai-agents",
|
|
16
|
-
"multi-agent",
|
|
17
|
-
"claude",
|
|
18
|
-
"collaboration",
|
|
19
|
-
"realtime",
|
|
20
|
-
"yjs"
|
|
21
|
-
],
|
|
22
|
-
"bin": {
|
|
23
|
-
"hivecode-mcp": "hive-mcp.js",
|
|
24
|
-
"hivecode-hook": "hive-hook-install.js",
|
|
25
|
-
"hivecode-await": "hive-await.js"
|
|
26
|
-
},
|
|
27
|
-
"files": [
|
|
28
|
-
"hive-mcp.js",
|
|
29
|
-
"hive-await.js",
|
|
30
|
-
"hive-listen.js",
|
|
31
|
-
"hive-session.js",
|
|
32
|
-
"hive-mux.js",
|
|
33
|
-
"hive-mux-proto.js",
|
|
34
|
-
"hive-
|
|
35
|
-
"hive-
|
|
36
|
-
"hive-
|
|
37
|
-
"hive-
|
|
38
|
-
"hive-
|
|
39
|
-
"hive-
|
|
40
|
-
"hive-
|
|
41
|
-
"hive-
|
|
42
|
-
"hive-
|
|
43
|
-
"hive-
|
|
44
|
-
"hive-
|
|
45
|
-
"hive-
|
|
46
|
-
"hive-
|
|
47
|
-
"hive-
|
|
48
|
-
"hive-
|
|
49
|
-
"hive-
|
|
50
|
-
"hive-
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"hive-
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"lang-
|
|
64
|
-
"lang-
|
|
65
|
-
"lang-
|
|
66
|
-
"lang-
|
|
67
|
-
"lang-
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"hive-
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"hive-
|
|
80
|
-
"hive-
|
|
81
|
-
"hive-
|
|
82
|
-
"hive-
|
|
83
|
-
"slack-
|
|
84
|
-
"
|
|
85
|
-
"slack-app-manifest
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
"docs/
|
|
90
|
-
"docs/
|
|
91
|
-
"docs/
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"test
|
|
107
|
-
"test:
|
|
108
|
-
"test:
|
|
109
|
-
"test:
|
|
110
|
-
"test:
|
|
111
|
-
"test:
|
|
112
|
-
"test:
|
|
113
|
-
"test:
|
|
114
|
-
"
|
|
115
|
-
"test:
|
|
116
|
-
"
|
|
117
|
-
"test:
|
|
118
|
-
"test:
|
|
119
|
-
"test:
|
|
120
|
-
"test:
|
|
121
|
-
"test:
|
|
122
|
-
"test:
|
|
123
|
-
"test:
|
|
124
|
-
"test:
|
|
125
|
-
"test:
|
|
126
|
-
"
|
|
127
|
-
"
|
|
128
|
-
"
|
|
129
|
-
"
|
|
130
|
-
"
|
|
131
|
-
"test:substrate
|
|
132
|
-
"test:substrate:
|
|
133
|
-
"test:substrate:
|
|
134
|
-
"test:
|
|
135
|
-
"test:
|
|
136
|
-
"test:
|
|
137
|
-
"test:
|
|
138
|
-
"test:
|
|
139
|
-
"test:
|
|
140
|
-
"test:
|
|
141
|
-
"test:
|
|
142
|
-
"test:
|
|
143
|
-
"test:
|
|
144
|
-
"test:
|
|
145
|
-
"test:
|
|
146
|
-
"test:
|
|
147
|
-
"
|
|
148
|
-
"
|
|
149
|
-
"
|
|
150
|
-
"demo:
|
|
151
|
-
"
|
|
152
|
-
"
|
|
153
|
-
"
|
|
154
|
-
"
|
|
155
|
-
"
|
|
156
|
-
"
|
|
157
|
-
"
|
|
158
|
-
"test:
|
|
159
|
-
"test:
|
|
160
|
-
"
|
|
161
|
-
"test:
|
|
162
|
-
"
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
"
|
|
171
|
-
"
|
|
172
|
-
"
|
|
173
|
-
"
|
|
174
|
-
"
|
|
175
|
-
"
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
"@
|
|
181
|
-
"
|
|
182
|
-
"
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "hivecode-mcp",
|
|
3
|
+
"version": "0.14.1",
|
|
4
|
+
"description": "MCP server that lets any AI coding agent join a Hivecode room — humans and multiple AI agents edit one live codebase with folder-scoped permissions and approval gates.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://hivecode.getgrm.tech",
|
|
8
|
+
"bugs": {
|
|
9
|
+
"url": "https://hivecode.getgrm.tech/contact",
|
|
10
|
+
"email": "support@getgrm.tech"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"mcp",
|
|
14
|
+
"model-context-protocol",
|
|
15
|
+
"ai-agents",
|
|
16
|
+
"multi-agent",
|
|
17
|
+
"claude",
|
|
18
|
+
"collaboration",
|
|
19
|
+
"realtime",
|
|
20
|
+
"yjs"
|
|
21
|
+
],
|
|
22
|
+
"bin": {
|
|
23
|
+
"hivecode-mcp": "hive-mcp.js",
|
|
24
|
+
"hivecode-hook": "hive-hook-install.js",
|
|
25
|
+
"hivecode-await": "hive-await.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"hive-mcp.js",
|
|
29
|
+
"hive-await.js",
|
|
30
|
+
"hive-listen.js",
|
|
31
|
+
"hive-session.js",
|
|
32
|
+
"hive-mux.js",
|
|
33
|
+
"hive-mux-proto.js",
|
|
34
|
+
"hive-transport.js",
|
|
35
|
+
"hive-poll-proto.js",
|
|
36
|
+
"hive-version.js",
|
|
37
|
+
"hive-pr-staleness.js",
|
|
38
|
+
"hive-pr.js",
|
|
39
|
+
"hive-branch.js", "hive-land.js", "hive-repos.js", "hive-room-mode.js", "hive-room-watcher.js",
|
|
40
|
+
"hive-mailbox.js",
|
|
41
|
+
"hive-obligations.js",
|
|
42
|
+
"hive-receipts.js",
|
|
43
|
+
"hive-throttle.js",
|
|
44
|
+
"hive-instructions.js",
|
|
45
|
+
"hive-activity.js",
|
|
46
|
+
"hive-relay-health.js",
|
|
47
|
+
"hive-privacy.js",
|
|
48
|
+
"hive-secrets.js",
|
|
49
|
+
"hive-room-key.js",
|
|
50
|
+
"hive-setup.js",
|
|
51
|
+
"hive-stdio.js",
|
|
52
|
+
"hive-update.js",
|
|
53
|
+
"docs/SELF_HOSTING.md",
|
|
54
|
+
"reconcile.cjs",
|
|
55
|
+
"hive-busy.js",
|
|
56
|
+
"hive-stop-hook.js",
|
|
57
|
+
"hive-hook-install.js",
|
|
58
|
+
"sync.js",
|
|
59
|
+
"core.js",
|
|
60
|
+
"limits.js",
|
|
61
|
+
"token.js",
|
|
62
|
+
"icr.js",
|
|
63
|
+
"lang-js.js",
|
|
64
|
+
"lang-brace.js",
|
|
65
|
+
"lang-python.js",
|
|
66
|
+
"lang-ruby.js",
|
|
67
|
+
"lang-json.js",
|
|
68
|
+
"lang-yaml.js",
|
|
69
|
+
"lang-toml.js",
|
|
70
|
+
"icr-merge.js",
|
|
71
|
+
"hive-coord.js",
|
|
72
|
+
"hive-authors.js",
|
|
73
|
+
"hive-gate.js",
|
|
74
|
+
"substrate.js",
|
|
75
|
+
"HIVE_RULES.md",
|
|
76
|
+
"docs/MCP.md",
|
|
77
|
+
"README.md",
|
|
78
|
+
"LICENSE",
|
|
79
|
+
"hive-github.js",
|
|
80
|
+
"hive-notify.js",
|
|
81
|
+
"hive-webhook.js",
|
|
82
|
+
"hive-slack.js",
|
|
83
|
+
"hive-slack-agent.js",
|
|
84
|
+
"hive-mcp-http.js",
|
|
85
|
+
"slack-app-manifest.json",
|
|
86
|
+
"slack-app-manifest-inbound.json",
|
|
87
|
+
"slack-app-manifest-agent.json",
|
|
88
|
+
"hive-time.js",
|
|
89
|
+
"docs/GITHUB_WORKFLOW.md",
|
|
90
|
+
"docs/QUICKSTART.md",
|
|
91
|
+
"docs/TROUBLESHOOTING.md",
|
|
92
|
+
"docs/SLACK_SETUP.md",
|
|
93
|
+
"docs/ALWAYS_ON.md"
|
|
94
|
+
],
|
|
95
|
+
"publishConfig": {
|
|
96
|
+
"access": "public"
|
|
97
|
+
},
|
|
98
|
+
"scripts": {
|
|
99
|
+
"prepare": "node scripts/install-hooks.mjs || exit 0",
|
|
100
|
+
"start": "node server.js",
|
|
101
|
+
"relay": "node server.js",
|
|
102
|
+
"sync:engine": "node sync-engine.mjs",
|
|
103
|
+
"check:engine": "node sync-engine.mjs --check",
|
|
104
|
+
"check:deps": "node scripts/check-deps.mjs",
|
|
105
|
+
"pretest": "node scripts/check-deps.mjs && node scripts/sync-engine.mjs --check && node scripts/check-files.mjs && node scripts/check-deploy.mjs",
|
|
106
|
+
"test": "node tests/test.js",
|
|
107
|
+
"test:features": "node tests/features-test.mjs",
|
|
108
|
+
"test:features:shape": "node tests/features-test.mjs --shape",
|
|
109
|
+
"test:learnings": "node tests/learnings-test.mjs",
|
|
110
|
+
"test:docs": "node tests/readme-promises-test.mjs && node tests/rules-promises-test.mjs && node tests/site-cli-usage-test.mjs",
|
|
111
|
+
"test:setup": "node tests/setup-test.mjs --package",
|
|
112
|
+
"test:mcp": "node tests/mcp-conformance-test.mjs",
|
|
113
|
+
"test:recreate": "node tests/blind-recreate-test.mjs",
|
|
114
|
+
"test:liveness": "node tests/presence-listener-test.mjs && node tests/agent-liveness-test.mjs && node tests/unreachable-recipient-test.mjs",
|
|
115
|
+
"test:attest": "node tests/attest-stale-test.mjs && node tests/hive-smp-test.js",
|
|
116
|
+
"build:ext": "node scripts/build-icr-cjs.cjs && node scripts/build-privacy-cjs.cjs",
|
|
117
|
+
"test:selfhost": "node tests/relay-pin-test.mjs && node tests/self-host-test.mjs && node tests/extension-privacy-parity-test.mjs",
|
|
118
|
+
"test:hardening": "node tests/genesis-claim-test.mjs && node tests/bare-root-write-test.mjs && node tests/version-truth-test.mjs && node tests/room-repo-drift-test.mjs && node tests/first-contact-refusal-test.mjs && node tests/first-contact-summary-test.mjs && node tests/open-file-cap-test.mjs && node tests/learnings-test.mjs && node tests/presence-listener-test.mjs && node tests/agent-liveness-test.mjs && node tests/unreachable-recipient-test.mjs && node tests/join-honesty-test.mjs && node tests/relay-diagnosis-test.mjs && node tests/blind-recreate-test.mjs && node tests/relay-pin-test.mjs && node tests/self-host-test.mjs && node tests/extension-privacy-parity-test.mjs && node tests/readme-promises-test.mjs && node tests/setup-test.mjs && node tests/mcp-conformance-test.mjs && node tests/update-notice-test.mjs && node tests/mux-test.mjs && node tests/own-files-quiet-test.mjs && node tests/wiped-relay-rejoin-test.mjs && node tests/token-budget-test.mjs && node tests/relay-presence-sweep-test.mjs && node tests/join-scale-test.mjs && node tests/join-queue-delete-test.mjs && node tests/delete-safety-test.mjs && node tests/relay-no-echo-test.mjs && node tests/genesis-collision-test.mjs && node tests/dead-heat-verdict-test.mjs && node tests/dead-heat-forced-test.mjs && node tests/deleted-dir-write-test.mjs && node tests/hive-await-test.mjs && node tests/listener-mail-once-test.mjs && node tests/build-identity-test.mjs && node tests/task-authority-test.mjs && node tests/grm-private-test.mjs && node tests/mixed-build-test.mjs && node tests/duplicate-name-test.mjs && node tests/unwritable-file-test.mjs && node tests/relay-claim-delete-test.mjs && node tests/secret-gate-test.mjs && node tests/package-closure-test.mjs && node tests/guessable-room-test.mjs && node tests/case-collision-test.mjs && node tests/case-rename-test.mjs && node tests/collided-notice-test.mjs && node tests/secured-invite-test.mjs && node tests/personal-room-test.mjs &&node tests/attest-stale-test.mjs && node tests/hive-smp-test.js && node tests/branch-test.mjs && node tests/unshared-binary-notice-test.mjs && node tests/binary-sync-test.mjs && node tests/doc-cap-remeasure-test.mjs && node tests/session-resume-test.mjs && node tests/shared-launch-folder-test.mjs && node tests/portable-agent-config-test.mjs",
|
|
119
|
+
"test:extension": "node tests/extension-parity-test.mjs && node tests/extension-privacy-parity-test.mjs",
|
|
120
|
+
"test:ceiling": "node tests/refused-visible-test.mjs && node tests/ceiling-no-data-loss-test.mjs",
|
|
121
|
+
"test:mux": "node tests/mux-test.mjs && node tests/mux-open-turns-test.mjs",
|
|
122
|
+
"test:live": "node scripts/live-stranger.mjs",
|
|
123
|
+
"test:tokens": "node tests/token-budget-test.mjs && node tests/status-cost-test.mjs",
|
|
124
|
+
"test:identity": "node tests/identity-audit-test.mjs",
|
|
125
|
+
"test:billing": "node tests/billing-test.mjs",
|
|
126
|
+
"test:license": "node tests/hive-license-test.js",
|
|
127
|
+
"test:money": "node tests/payment-e2e-test.mjs && node tests/subscribe-test.mjs && node tests/lifecycle-test.mjs && node tests/billing-test.mjs && node tests/hive-license-test.js && node tests/recover-test.mjs",
|
|
128
|
+
"check:web": "tsc --noEmit",
|
|
129
|
+
"build:web": "esbuild web/src/main.ts --bundle --minify --format=iife --target=es2019 --outfile=public/app.js",
|
|
130
|
+
"build:crdt": "esbuild web/crdt.js --bundle --minify --format=esm --target=es2019 --outfile=public/hive-crdt.js",
|
|
131
|
+
"test:substrate": "node substrate-test.js",
|
|
132
|
+
"test:substrate:live": "node substrate-live-test.js",
|
|
133
|
+
"test:substrate:enforce": "node substrate-enforce-test.js",
|
|
134
|
+
"test:substrate:authority": "node substrate-authority-test.js",
|
|
135
|
+
"test:substrate:all": "node substrate-test.js && node substrate-live-test.js && node substrate-enforce-test.js && node substrate-authority-test.js",
|
|
136
|
+
"test:recover": "node tests/recover-test.mjs",
|
|
137
|
+
"test:mailbox": "node tests/mailbox-test.mjs && node tests/mcp-wait-test.mjs && node tests/mailbox-noise-test.mjs",
|
|
138
|
+
"test:stophook": "node tests/stop-hook-test.mjs",
|
|
139
|
+
"test:limits": "node tests/limits-test.mjs && node tests/rate-hold-test.mjs && node tests/persist-batch-test.mjs",
|
|
140
|
+
"test:merge": "node tests/diff3-test.mjs && node tests/merge-balloon-test.mjs && node tests/icr-merge-test.js && node tests/icr-gap-comments-test.mjs && node tests/icr-comment-fuzz-test.mjs",
|
|
141
|
+
"test:rejoin": "node tests/rejoin-clobber-test.mjs",
|
|
142
|
+
"test:prod": "node tests/test.js && node tests/firstrun-test.mjs && node tests/credential-split-test.mjs && node tests/limits-test.mjs && node tests/usage-meter-test.mjs && node tests/rejoin-clobber-test.mjs && node tests/stop-hook-test.mjs && node tests/coordination-test.mjs && node tests/control-panel-test.mjs && node tests/hive-map-test.mjs && node tests/hive-gate-test.mjs && node tests/durability-test.mjs && node tests/payment-e2e-test.mjs && node tests/subscribe-test.mjs && node tests/lifecycle-test.mjs && node tests/billing-test.mjs && node tests/hive-license-test.js && node tests/recover-test.mjs && node demo/wrap-test.mjs",
|
|
143
|
+
"test:meter": "node tests/usage-meter-test.mjs",
|
|
144
|
+
"test:subscribe": "node tests/subscribe-test.mjs",
|
|
145
|
+
"test:cred": "node tests/credential-split-test.mjs",
|
|
146
|
+
"test:firstrun": "node tests/firstrun-test.mjs",
|
|
147
|
+
"test:lifecycle": "node tests/lifecycle-test.mjs",
|
|
148
|
+
"test:payment": "node tests/payment-e2e-test.mjs",
|
|
149
|
+
"scorecard": "node scorecard.mjs",
|
|
150
|
+
"demo:video": "node demo/record.mjs",
|
|
151
|
+
"test:wrap": "node demo/wrap-test.mjs",
|
|
152
|
+
"demo:panel": "node demo/record-panel.mjs",
|
|
153
|
+
"demo:all": "node demo/record.mjs && node demo/record-panel.mjs",
|
|
154
|
+
"check:files": "node scripts/check-files.mjs",
|
|
155
|
+
"prepublishOnly": "node scripts/check-files.mjs",
|
|
156
|
+
"demo:cast": "node demo/cast.mjs --dry-run",
|
|
157
|
+
"check:deploy": "node scripts/check-deploy.mjs",
|
|
158
|
+
"test:coordination": "node tests/coordination-test.mjs",
|
|
159
|
+
"test:panel": "node tests/control-panel-test.mjs && node tests/control-room-walk.mjs",
|
|
160
|
+
"test:map": "node tests/hive-map-test.mjs",
|
|
161
|
+
"test:gate": "node tests/hive-gate-test.mjs",
|
|
162
|
+
"bench:ab": "node bench/coordination-ab.mjs",
|
|
163
|
+
"test:branch": "node tests/branch-test.mjs",
|
|
164
|
+
"test:github": "node tests/github-cli-test.mjs && node tests/notify-test.mjs && node tests/github-watcher-test.mjs"
|
|
165
|
+
},
|
|
166
|
+
"engines": {
|
|
167
|
+
"node": ">=18"
|
|
168
|
+
},
|
|
169
|
+
"dependencies": {
|
|
170
|
+
"acorn": "^8.17.0",
|
|
171
|
+
"ignore": "^7.0.5",
|
|
172
|
+
"lib0": "^0.2.117",
|
|
173
|
+
"lodash.debounce": "^4.0.8",
|
|
174
|
+
"ws": "^8.18.0",
|
|
175
|
+
"y-protocols": "^1.0.6",
|
|
176
|
+
"y-websocket": "^3.1.0",
|
|
177
|
+
"yjs": "^13.6.18"
|
|
178
|
+
},
|
|
179
|
+
"devDependencies": {
|
|
180
|
+
"@anthropic-ai/sdk": "^0.104.2",
|
|
181
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
182
|
+
"@types/node": "^26.1.2",
|
|
183
|
+
"esbuild": "^0.28.1",
|
|
184
|
+
"typescript": "^7.0.2"
|
|
185
|
+
},
|
|
186
|
+
"main": "core.js",
|
|
187
|
+
"directories": {
|
|
188
|
+
"doc": "docs",
|
|
189
|
+
"test": "tests"
|
|
190
|
+
},
|
|
191
|
+
"author": "Ganesh Shivlal Kute <support@getgrm.tech>"
|
|
192
|
+
}
|
package/reconcile.cjs
CHANGED
|
@@ -250,24 +250,27 @@ function summarizeChange(base, next) {
|
|
|
250
250
|
|
|
251
251
|
// 3-way merge for the sync layer (disk <-> shared doc)
|
|
252
252
|
function merge3(base, mine, theirs) {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
if (
|
|
253
|
+
const norm = (s) => (s || '').replace(/\r\n/g, '\n')
|
|
254
|
+
const nm0 = norm(mine), nt0 = norm(theirs), nb0 = norm(base)
|
|
255
|
+
if (nm0 === nt0) return { text: nt0, conflict: false }
|
|
256
|
+
if (nb0 === nt0) return { text: nm0, conflict: false }
|
|
257
|
+
if (nb0 === nm0) return { text: nt0, conflict: false }
|
|
256
258
|
|
|
257
259
|
const cleanBase = hasConflictMarkers(base) ? stripConflictMarkers(base, 'local') : (base || '')
|
|
258
260
|
const cleanMine = hasConflictMarkers(mine) ? stripConflictMarkers(mine, 'local') : (mine || '')
|
|
259
261
|
const cleanTheirs = hasConflictMarkers(theirs) ? stripConflictMarkers(theirs, 'theirs') : (theirs || '')
|
|
260
262
|
|
|
261
|
-
|
|
262
|
-
if (
|
|
263
|
-
if (
|
|
263
|
+
const nm = norm(cleanMine), nt = norm(cleanTheirs), nb = norm(cleanBase)
|
|
264
|
+
if (nm === nt) return { text: nt, conflict: false }
|
|
265
|
+
if (nb === nt) return { text: nm, conflict: false }
|
|
266
|
+
if (nb === nm) return { text: nt, conflict: false }
|
|
264
267
|
|
|
265
|
-
const b =
|
|
266
|
-
const d3 = diff3Lines(b,
|
|
268
|
+
const b = nb.split('\n')
|
|
269
|
+
const d3 = diff3Lines(b, nm.split('\n'), nt.split('\n'))
|
|
267
270
|
if (d3) return { text: d3.lines.join('\n'), conflict: d3.conflict }
|
|
268
271
|
// Past diff3's work bound (two sides that share almost nothing): one range per side.
|
|
269
|
-
const mr = changedRange(b,
|
|
270
|
-
const tr = changedRange(b,
|
|
272
|
+
const mr = changedRange(b, nm.split('\n'))
|
|
273
|
+
const tr = changedRange(b, nt.split('\n'))
|
|
271
274
|
if (mr.endBase <= tr.startBase || tr.endBase <= mr.startBase) {
|
|
272
275
|
const out = b.slice()
|
|
273
276
|
for (const e of [mr, tr].sort((x, y) => y.startBase - x.startBase)) {
|
|
@@ -279,6 +282,10 @@ function merge3(base, mine, theirs) {
|
|
|
279
282
|
const end = Math.max(mr.endBase, tr.endBase)
|
|
280
283
|
const mineBlock = [...b.slice(start, mr.startBase), ...mr.newLines, ...b.slice(mr.endBase, end)]
|
|
281
284
|
const theirsBlock = [...b.slice(start, tr.startBase), ...tr.newLines, ...b.slice(tr.endBase, end)]
|
|
285
|
+
if (mineBlock.length === theirsBlock.length && mineBlock.every((l, k) => l === theirsBlock[k])) {
|
|
286
|
+
const out = [...b.slice(0, start), ...theirsBlock, ...b.slice(end)]
|
|
287
|
+
return { text: out.join('\n'), conflict: false }
|
|
288
|
+
}
|
|
282
289
|
const out = [
|
|
283
290
|
...b.slice(0, start),
|
|
284
291
|
'<<<<<<< local (yours)',
|