burhan-mop 0.1.7 → 0.1.8
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/.MOP/PROTOCOL.md +33 -0
- package/.MOP/STATE.json +34 -1
- package/.MOP/scripts/mop-core.mjs +124 -17
- package/.agents/AGENTS.md +8 -0
- package/AGENTS.md +10 -1
- package/CLAUDE.md +8 -0
- package/GEMINI.md +5 -0
- package/README.bm.md +1 -1
- package/README.md +1 -1
- package/package.json +1 -1
package/.MOP/PROTOCOL.md
CHANGED
|
@@ -123,6 +123,11 @@ Routing rules:
|
|
|
123
123
|
genuinely requires several areas of expertise.
|
|
124
124
|
- If the route reports `partyMode.active: true`, run Party Mode before the final
|
|
125
125
|
answer. Name any missing participant agents first.
|
|
126
|
+
- If the route reports `nextAction: "name-required-party-agents"`, stop and ask
|
|
127
|
+
every question in `missingAgentQuestions`. Do not continue with the task until
|
|
128
|
+
all required party agents have names.
|
|
129
|
+
- Explicit requests such as `party mode`, `multi-agent`, `semua agent`, or
|
|
130
|
+
`agent bincang` must activate Party Mode automatically.
|
|
126
131
|
- The route JSON includes an `answerContract`. The assistant must restore
|
|
127
132
|
monthly memory, start the visible answer with `answerContract.firstLine`, and
|
|
128
133
|
save a one-line memory after meaningful work.
|
|
@@ -163,6 +168,8 @@ PARTY MODE
|
|
|
163
168
|
- Do not include irrelevant agents just because they exist.
|
|
164
169
|
- If a needed party role has no named agent, ask the user to name that agent
|
|
165
170
|
before using it.
|
|
171
|
+
- If several party agents are missing, ask for all missing names in one reply:
|
|
172
|
+
`Kita ada <N> agent belum ada nama. Beri nama untuk ...`
|
|
166
173
|
|
|
167
174
|
Visible dialogue format:
|
|
168
175
|
|
|
@@ -188,6 +195,32 @@ agent: <from-name> (<from-role>)
|
|
|
188
195
|
<explanation>
|
|
189
196
|
```
|
|
190
197
|
|
|
198
|
+
## Browser And Scraping Gate
|
|
199
|
+
|
|
200
|
+
Browser, scraping, rendered extraction, clicking, login flow, bot-detection, and
|
|
201
|
+
form-filling tasks must pass browser preflight before any browser automation.
|
|
202
|
+
|
|
203
|
+
Run:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
node .MOP/scripts/mop-core.mjs browser preflight
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Rules:
|
|
210
|
+
|
|
211
|
+
- First scan the default browser automatically. On Linux this uses
|
|
212
|
+
`xdg-settings get default-web-browser`; fallback is `$BROWSER`.
|
|
213
|
+
- If Chrome or Chromium is detected, browser automation may proceed with normal
|
|
214
|
+
Chrome-compatible mode.
|
|
215
|
+
- If Edge, Brave, or Opera is detected, use browser-act `chrome-direct` mode and
|
|
216
|
+
guide the user to start that browser with `--remote-debugging-port`.
|
|
217
|
+
- If no supported browser is detected, ask the user which browser they use
|
|
218
|
+
before scraping or browser automation.
|
|
219
|
+
- Do not start a default Chrome session first when the user uses Edge, Brave, or
|
|
220
|
+
Opera.
|
|
221
|
+
- If `agent route` includes `browserPreflight.needsQuestion: true`, ask
|
|
222
|
+
`browserPreflight.question` and stop.
|
|
223
|
+
|
|
191
224
|
## MOP Workflow
|
|
192
225
|
|
|
193
226
|
MOP Workflow is BMAD-inspired and MOP-native. It is the default
|
package/.MOP/STATE.json
CHANGED
|
@@ -77,7 +77,34 @@
|
|
|
77
77
|
"Normal Party mode should use at least 3 participants and prefer 4 when the task has enough relevant roles.",
|
|
78
78
|
"The primary agent coordinates the party and keeps the user intent visible.",
|
|
79
79
|
"Every visible agent message must use the configured dialogue format.",
|
|
80
|
-
"Agents should ask each other focused questions, answer directly, then hand a clear result to the user."
|
|
80
|
+
"Agents should ask each other focused questions, answer directly, then hand a clear result to the user.",
|
|
81
|
+
"Explicit requests such as party mode, multi-agent, semua agent, or agent discussion must activate Party Mode.",
|
|
82
|
+
"If Party Mode needs unnamed agents, ask for all missing agent names before doing the task."
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
"browserPolicy": {
|
|
86
|
+
"requirePreflightBeforeBrowserWork": true,
|
|
87
|
+
"requireDefaultBrowserCheck": true,
|
|
88
|
+
"supportedChoices": [
|
|
89
|
+
"Chrome",
|
|
90
|
+
"Edge",
|
|
91
|
+
"Brave",
|
|
92
|
+
"Opera"
|
|
93
|
+
],
|
|
94
|
+
"builtinChromeBrowsers": [
|
|
95
|
+
"chrome",
|
|
96
|
+
"chromium"
|
|
97
|
+
],
|
|
98
|
+
"directModeBrowsers": [
|
|
99
|
+
"brave",
|
|
100
|
+
"edge",
|
|
101
|
+
"opera"
|
|
102
|
+
],
|
|
103
|
+
"rules": [
|
|
104
|
+
"Before browser, scraping, extraction, click automation, login flow, or form filling, run browser preflight.",
|
|
105
|
+
"Check the user's default browser automatically when possible.",
|
|
106
|
+
"If the default browser is Edge, Brave, or Opera, use chrome-direct mode and guide the user to start remote debugging.",
|
|
107
|
+
"If no supported browser is detected, ask the user which browser they use before continuing."
|
|
81
108
|
]
|
|
82
109
|
},
|
|
83
110
|
"workflow": {
|
|
@@ -531,6 +558,12 @@
|
|
|
531
558
|
"kind": "operations",
|
|
532
559
|
"purpose": "GitHub repo, branch, PR, issue, release, and merge workflow."
|
|
533
560
|
},
|
|
561
|
+
{
|
|
562
|
+
"role": "browser",
|
|
563
|
+
"title": "Browser Automation Agent",
|
|
564
|
+
"kind": "operations",
|
|
565
|
+
"purpose": "Browser preflight, scraping, rendered extraction, clicking, form filling, login flows, and browser-act coordination."
|
|
566
|
+
},
|
|
534
567
|
{
|
|
535
568
|
"role": "devops",
|
|
536
569
|
"title": "DevOps Engineer",
|
|
@@ -232,6 +232,66 @@ function answerContractFor(state, actor, agent = activeAgentFor(state, actor)) {
|
|
|
232
232
|
};
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
+
function browserPolicy(state) {
|
|
236
|
+
return state.browserPolicy || {
|
|
237
|
+
requirePreflightBeforeBrowserWork: true,
|
|
238
|
+
requireDefaultBrowserCheck: true,
|
|
239
|
+
directModeBrowsers: ['brave', 'edge', 'opera'],
|
|
240
|
+
builtinChromeBrowsers: ['chrome', 'chromium'],
|
|
241
|
+
supportedChoices: ['Chrome', 'Edge', 'Brave', 'Opera']
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function detectDefaultBrowser() {
|
|
246
|
+
const xdg = spawnSync('xdg-settings', ['get', 'default-web-browser'], {
|
|
247
|
+
cwd: rootDir,
|
|
248
|
+
encoding: 'utf8'
|
|
249
|
+
});
|
|
250
|
+
const raw = (xdg.status === 0 ? xdg.stdout : '').trim() || process.env.BROWSER || '';
|
|
251
|
+
const value = raw.toLowerCase();
|
|
252
|
+
let family = 'unknown';
|
|
253
|
+
if (/(google-chrome|chrome)/.test(value) && !/chromium/.test(value)) family = 'chrome';
|
|
254
|
+
else if (/chromium/.test(value)) family = 'chromium';
|
|
255
|
+
else if (/brave/.test(value)) family = 'brave';
|
|
256
|
+
else if (/(microsoft-edge|edge)/.test(value)) family = 'edge';
|
|
257
|
+
else if (/opera/.test(value)) family = 'opera';
|
|
258
|
+
else if (/firefox/.test(value)) family = 'firefox';
|
|
259
|
+
return {
|
|
260
|
+
raw: raw || null,
|
|
261
|
+
family,
|
|
262
|
+
source: raw ? (xdg.status === 0 ? 'xdg-settings' : 'BROWSER') : 'not-detected'
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function browserPreflightFor(state) {
|
|
267
|
+
const policy = browserPolicy(state);
|
|
268
|
+
const detected = detectDefaultBrowser();
|
|
269
|
+
const direct = (policy.directModeBrowsers || []).includes(detected.family);
|
|
270
|
+
const builtin = (policy.builtinChromeBrowsers || []).includes(detected.family);
|
|
271
|
+
const supported = direct || builtin;
|
|
272
|
+
const mode = builtin ? 'chrome' : direct ? 'chrome-direct' : 'ask-user-browser';
|
|
273
|
+
const needsQuestion = !supported;
|
|
274
|
+
return {
|
|
275
|
+
required: policy.requirePreflightBeforeBrowserWork !== false,
|
|
276
|
+
defaultBrowser: detected,
|
|
277
|
+
mode,
|
|
278
|
+
ready: supported,
|
|
279
|
+
needsQuestion,
|
|
280
|
+
question: needsQuestion
|
|
281
|
+
? `Saya tak dapat kesan Chrome/Edge/Brave/Opera sebagai browser default. Awak guna browser apa? Pilih: ${(policy.supportedChoices || ['Chrome', 'Edge', 'Brave', 'Opera']).join(', ')}.`
|
|
282
|
+
: '',
|
|
283
|
+
instructions: direct
|
|
284
|
+
? [
|
|
285
|
+
`Use browser-act chrome-direct for ${detected.family}.`,
|
|
286
|
+
'Guide the user to start that browser with --remote-debugging-port before scraping or form automation.',
|
|
287
|
+
'Do not create a default chrome session first.'
|
|
288
|
+
]
|
|
289
|
+
: builtin
|
|
290
|
+
? ['Use normal Chrome-compatible browser automation.', 'Do not ask the user again unless automation fails.']
|
|
291
|
+
: ['Ask the user which browser they use before scraping or browser automation.']
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
|
|
235
295
|
function requireActiveAgent(state, actor, role = 'core', title = 'Core Agent') {
|
|
236
296
|
const agent = activeAgentFor(state, actor);
|
|
237
297
|
if (agent) return agent;
|
|
@@ -383,7 +443,7 @@ const routeRules = [
|
|
|
383
443
|
{
|
|
384
444
|
role: 'browser',
|
|
385
445
|
support: ['researcher', 'tester'],
|
|
386
|
-
keywords: ['browser', 'browse', 'scrape', 'scraping', 'extract', 'click', 'login flow', 'fill form', 'captcha', 'bot detection', 'website', 'url', 'webpage']
|
|
446
|
+
keywords: ['agent browser', 'browser agent', 'browser automation', 'browser', 'browse', 'scrape', 'scraping', 'web scraping', 'extract', 'click', 'login flow', 'fill form', 'captcha', 'bot detection', 'website', 'url', 'webpage']
|
|
387
447
|
},
|
|
388
448
|
{
|
|
389
449
|
role: 'researcher',
|
|
@@ -407,6 +467,10 @@ function routeScore(task, rule) {
|
|
|
407
467
|
return rule.keywords.reduce((score, keyword) => task.includes(keyword) ? score + Math.max(1, keyword.split(/\s+/).length) : score, 0);
|
|
408
468
|
}
|
|
409
469
|
|
|
470
|
+
function hasBrowserWorkIntent(task) {
|
|
471
|
+
return /\b(agent browser|browser agent|browser automation|browse|scrape|scraping|web scraping|extract|click|login flow|fill form|captcha|bot detection|webpage|url)\b/.test(task);
|
|
472
|
+
}
|
|
473
|
+
|
|
410
474
|
function uniqueValues(values) {
|
|
411
475
|
return [...new Set(values.filter(Boolean))];
|
|
412
476
|
}
|
|
@@ -420,6 +484,7 @@ function maybeLimit(values, limit) {
|
|
|
420
484
|
|
|
421
485
|
function shouldActivatePartyMode(state, task, primaryRole, supportRoles, newSystemIntent) {
|
|
422
486
|
if (state.partyMode?.enabled === false || state.partyMode?.autoActivateWhenNeeded === false) return false;
|
|
487
|
+
const explicitPartyIntent = /\b(party mode|party|multi[- ]?agent|swarm|semua agent|banyak agent|agent.*bincang|bincang.*agent|agent.*discuss|discuss.*agent)\b/.test(task);
|
|
423
488
|
const multiDomainIntent = [
|
|
424
489
|
['ui', 'backend'],
|
|
425
490
|
['frontend', 'backend'],
|
|
@@ -429,10 +494,11 @@ function shouldActivatePartyMode(state, task, primaryRole, supportRoles, newSyst
|
|
|
429
494
|
['security', 'auth'],
|
|
430
495
|
['prompt', 'system']
|
|
431
496
|
].some(([first, second]) => task.includes(first) && task.includes(second));
|
|
497
|
+
const browserRiskIntent = hasBrowserWorkIntent(task);
|
|
432
498
|
const connectiveIntent = /\b(connect|connected|integrate|integration|bersambung|sambung|hubung|flow|workflow)\b/.test(task);
|
|
433
499
|
const broadBuild = newSystemIntent && supportRoles.length >= 2;
|
|
434
500
|
const specialistStack = supportRoles.length >= 3 && ['architect', 'planner', 'core'].includes(primaryRole);
|
|
435
|
-
return multiDomainIntent || connectiveIntent || broadBuild || specialistStack;
|
|
501
|
+
return explicitPartyIntent || multiDomainIntent || browserRiskIntent || connectiveIntent || broadBuild || specialistStack;
|
|
436
502
|
}
|
|
437
503
|
|
|
438
504
|
function partyFormat(state) {
|
|
@@ -453,12 +519,14 @@ function partyParticipantsFor(state, primaryRole, supportRoles, scored, partyAct
|
|
|
453
519
|
const minimum = Number(state.partyMode?.minimumParticipants || 3);
|
|
454
520
|
const floor = Number.isFinite(preferredMinimum) ? Math.max(minimum, preferredMinimum) : minimum;
|
|
455
521
|
const fallbackRoles = ['planner', 'researcher', 'reviewer', 'coder', 'architect', 'prompt', 'tester'];
|
|
456
|
-
const
|
|
522
|
+
const relevant = uniqueValues([
|
|
457
523
|
primaryRole,
|
|
458
524
|
...supportRoles,
|
|
459
|
-
...scored.map((rule) => rule.role)
|
|
460
|
-
...fallbackRoles
|
|
525
|
+
...scored.map((rule) => rule.role)
|
|
461
526
|
]);
|
|
527
|
+
const participants = relevant.length >= floor
|
|
528
|
+
? relevant
|
|
529
|
+
: uniqueValues([...relevant, ...fallbackRoles]).slice(0, floor);
|
|
462
530
|
const catalogRoles = new Set((state.agentCatalog || []).map((item) => item.role));
|
|
463
531
|
const filtered = participants.filter((role) => catalogRoles.has(role));
|
|
464
532
|
const enough = filtered.length >= floor ? filtered : participants;
|
|
@@ -476,15 +544,16 @@ function inferAgentRoute(state, taskText) {
|
|
|
476
544
|
const newSystemIntent = /\b(system|sistem|app|tool|platform|website|dashboard|engine|core)\b/.test(task)
|
|
477
545
|
|| /buat sebuah|bina sebuah|create a|build a/.test(task);
|
|
478
546
|
const implementationIntent = /\b(code|coding|implement|fix|ubah file|buat file)\b/.test(task);
|
|
547
|
+
const browserWorkIntent = hasBrowserWorkIntent(task);
|
|
479
548
|
const top = scored[0];
|
|
480
|
-
let primaryRole = top?.role || state.agentPolicy?.defaultRole || 'core';
|
|
549
|
+
let primaryRole = browserWorkIntent ? 'browser' : (top?.role || state.agentPolicy?.defaultRole || 'core');
|
|
481
550
|
|
|
482
|
-
if (newSystemIntent && !implementationIntent && state.agentRouter?.preferHighReasoningForNewSystems !== false) {
|
|
551
|
+
if (newSystemIntent && !implementationIntent && !browserWorkIntent && state.agentRouter?.preferHighReasoningForNewSystems !== false) {
|
|
483
552
|
primaryRole = state.agentRouter?.defaultHighReasoningRole || 'architect';
|
|
484
553
|
}
|
|
485
554
|
|
|
486
555
|
const primary = catalogForRole(state, primaryRole);
|
|
487
|
-
const baseSupport = newSystemIntent
|
|
556
|
+
const baseSupport = newSystemIntent && !browserWorkIntent
|
|
488
557
|
? ['planner', 'researcher', 'prompt', 'coder', 'reviewer']
|
|
489
558
|
: (top?.support || []);
|
|
490
559
|
const supportRoles = maybeLimit(uniqueValues([
|
|
@@ -495,7 +564,7 @@ function inferAgentRoute(state, taskText) {
|
|
|
495
564
|
const partyActive = shouldActivatePartyMode(state, task, primaryRole, supportRoles, newSystemIntent);
|
|
496
565
|
const partyParticipants = partyParticipantsFor(state, primaryRole, supportRoles, scored, partyActive);
|
|
497
566
|
|
|
498
|
-
const ambiguousNewSystem = newSystemIntent && words.length < 18;
|
|
567
|
+
const ambiguousNewSystem = newSystemIntent && !browserWorkIntent && words.length < 18;
|
|
499
568
|
const noClearMatch = scored.length === 0 && words.length > 3;
|
|
500
569
|
const needsClarification = state.agentRouter?.clarifyBeforeActionWhenAmbiguous !== false
|
|
501
570
|
&& (ambiguousNewSystem || noClearMatch || /\b(maybe|mungkin|lebih kurang|macam)\b/.test(task));
|
|
@@ -526,7 +595,7 @@ function inferAgentRoute(state, taskText) {
|
|
|
526
595
|
confidence: top ? Math.min(0.95, 0.45 + (top.score * 0.08)) : 0.35,
|
|
527
596
|
needsClarification,
|
|
528
597
|
questions,
|
|
529
|
-
reason: newSystemIntent
|
|
598
|
+
reason: newSystemIntent && !browserWorkIntent
|
|
530
599
|
? `New or broad system task routed to ${primary.title} for high-reasoning planning before implementation.`
|
|
531
600
|
: top
|
|
532
601
|
? `Matched keywords for ${primary.title}: ${top.keywords.filter((keyword) => task.includes(keyword)).join(', ')}.`
|
|
@@ -734,13 +803,27 @@ function agentRoute(args) {
|
|
|
734
803
|
};
|
|
735
804
|
}) : [];
|
|
736
805
|
const missingPartyAgents = partyAgents.filter((item) => item.missing);
|
|
806
|
+
const missingAgentCommands = missingPartyAgents.map((item) => (
|
|
807
|
+
`node .MOP/scripts/mop-core.mjs agent activate --actor ${actor} --role ${item.role} --title "${item.title}" --name "<agent-name>"`
|
|
808
|
+
));
|
|
809
|
+
const missingAgentQuestions = missingPartyAgents.map((item) => (
|
|
810
|
+
`Beri nama untuk ${item.title} (${item.role}) kamu:`
|
|
811
|
+
));
|
|
812
|
+
const browserPreflight = route.primaryRole === 'browser'
|
|
813
|
+
|| route.supportRoles.includes('browser')
|
|
814
|
+
|| route.partyMode?.participants?.includes('browser')
|
|
815
|
+
|| hasBrowserWorkIntent(route.task || '')
|
|
816
|
+
? browserPreflightFor(state)
|
|
817
|
+
: null;
|
|
737
818
|
const response = {
|
|
738
819
|
ok: Boolean(agent),
|
|
739
820
|
actor,
|
|
740
821
|
route,
|
|
741
822
|
partyAgents,
|
|
823
|
+
missingAgents: missingPartyAgents,
|
|
742
824
|
activeAgent: null,
|
|
743
825
|
answerContract: null,
|
|
826
|
+
browserPreflight,
|
|
744
827
|
monthlyMemory: {
|
|
745
828
|
restoreCommand: `node .MOP/scripts/mop-core.mjs memory brief --actor ${actor}`,
|
|
746
829
|
saveCommand: `node .MOP/scripts/mop-core.mjs memory add --actor ${actor} --kind conversation --summary "<one-line outcome>"`
|
|
@@ -763,18 +846,33 @@ function agentRoute(args) {
|
|
|
763
846
|
if (route.partyMode.active && missingPartyAgents.length) {
|
|
764
847
|
response.ok = false;
|
|
765
848
|
response.nextAction = 'name-required-party-agents';
|
|
766
|
-
response.message =
|
|
767
|
-
response.
|
|
768
|
-
|
|
769
|
-
|
|
849
|
+
response.message = `Party Mode perlukan ${missingPartyAgents.length} agent yang belum ada nama. Minta nama semua agent ini dahulu sebelum sambung kerja.`;
|
|
850
|
+
response.ask = `Kita ada ${missingPartyAgents.length} agent belum ada nama. ${missingAgentQuestions.join(' ')}`;
|
|
851
|
+
response.missingAgentQuestions = missingAgentQuestions;
|
|
852
|
+
response.missingAgentCommands = missingAgentCommands;
|
|
853
|
+
} else if (browserPreflight?.required && browserPreflight.needsQuestion) {
|
|
854
|
+
response.ok = false;
|
|
855
|
+
response.nextAction = 'ask-browser-before-browser-work';
|
|
856
|
+
response.message = 'Browser preflight belum ready. Tanya browser user dahulu sebelum scraping/browser automation.';
|
|
857
|
+
response.ask = browserPreflight.question;
|
|
770
858
|
} else {
|
|
771
859
|
response.nextAction = route.needsClarification ? 'ask-clarifying-questions' : 'proceed-with-agent';
|
|
772
860
|
}
|
|
773
861
|
} else {
|
|
774
|
-
response.nextAction =
|
|
775
|
-
|
|
776
|
-
|
|
862
|
+
response.nextAction = route.partyMode.active && missingPartyAgents.length
|
|
863
|
+
? 'name-required-party-agents'
|
|
864
|
+
: 'name-required-agent';
|
|
865
|
+
response.message = route.partyMode.active && missingPartyAgents.length
|
|
866
|
+
? `Party Mode perlukan ${missingPartyAgents.length} agent yang belum ada nama. Minta nama semua agent ini dahulu sebelum sambung kerja.`
|
|
867
|
+
: `Task ini perlukan ${route.primaryTitle}. Agent ini belum ada nama lagi atau belum dipilih.`;
|
|
868
|
+
response.ask = route.partyMode.active && missingPartyAgents.length
|
|
869
|
+
? `Kita ada ${missingPartyAgents.length} agent belum ada nama. ${missingAgentQuestions.join(' ')}`
|
|
870
|
+
: `Beri nama untuk ${route.primaryTitle} kamu:`;
|
|
777
871
|
response.command = `node .MOP/scripts/mop-core.mjs agent activate --actor ${actor} --role ${route.primaryRole} --title "${route.primaryTitle}" --name "<agent-name>"`;
|
|
872
|
+
if (route.partyMode.active && missingPartyAgents.length) {
|
|
873
|
+
response.missingAgentQuestions = missingAgentQuestions;
|
|
874
|
+
response.missingAgentCommands = missingAgentCommands;
|
|
875
|
+
}
|
|
778
876
|
if (route.needsClarification) response.afterNaming = route.questions;
|
|
779
877
|
}
|
|
780
878
|
|
|
@@ -789,6 +887,11 @@ function agentList() {
|
|
|
789
887
|
}, null, 2));
|
|
790
888
|
}
|
|
791
889
|
|
|
890
|
+
function browserPreflight() {
|
|
891
|
+
const state = readState();
|
|
892
|
+
console.log(JSON.stringify(browserPreflightFor(state), null, 2));
|
|
893
|
+
}
|
|
894
|
+
|
|
792
895
|
function memoryAdd(args) {
|
|
793
896
|
const state = readState();
|
|
794
897
|
if (!state.initialized) throw new Error('MOP is not initialized.');
|
|
@@ -883,6 +986,7 @@ function validate() {
|
|
|
883
986
|
if (state.agentPolicy && typeof state.agentPolicy !== 'object') errors.push('agentPolicy must be object');
|
|
884
987
|
if (state.answerPolicy && typeof state.answerPolicy !== 'object') errors.push('answerPolicy must be object');
|
|
885
988
|
if (state.memoryPolicy && typeof state.memoryPolicy !== 'object') errors.push('memoryPolicy must be object');
|
|
989
|
+
if (state.browserPolicy && typeof state.browserPolicy !== 'object') errors.push('browserPolicy must be object');
|
|
886
990
|
if (state.agentRouter && typeof state.agentRouter !== 'object') errors.push('agentRouter must be object');
|
|
887
991
|
if (state.partyMode && typeof state.partyMode !== 'object') errors.push('partyMode must be object');
|
|
888
992
|
if (state.autosync?.githubIdentity && typeof state.autosync.githubIdentity !== 'object') {
|
|
@@ -970,6 +1074,7 @@ function status() {
|
|
|
970
1074
|
agentPolicy: state.agentPolicy || {},
|
|
971
1075
|
answerPolicy: answerPolicy(state),
|
|
972
1076
|
memoryPolicy: memoryPolicy(state),
|
|
1077
|
+
browserPolicy: browserPolicy(state),
|
|
973
1078
|
agentRouter: state.agentRouter || {},
|
|
974
1079
|
partyMode: state.partyMode || {},
|
|
975
1080
|
workflow: {
|
|
@@ -1023,6 +1128,7 @@ function main() {
|
|
|
1023
1128
|
if (command === 'agent' && subcommand === 'require') return agentRequire(args);
|
|
1024
1129
|
if (command === 'agent' && subcommand === 'route') return agentRoute(args);
|
|
1025
1130
|
if (command === 'agent' && subcommand === 'list') return agentList();
|
|
1131
|
+
if (command === 'browser' && subcommand === 'preflight') return browserPreflight();
|
|
1026
1132
|
if (command === 'memory' && subcommand === 'add') return memoryAdd(args);
|
|
1027
1133
|
if (command === 'memory' && subcommand === 'brief') return memoryBrief(args);
|
|
1028
1134
|
if (command === 'memory' && subcommand === 'restore') return memoryRestore(args);
|
|
@@ -1039,6 +1145,7 @@ function main() {
|
|
|
1039
1145
|
node .MOP/scripts/mop-core.mjs agent require --actor CODE [--role ROLE] [--title TITLE]
|
|
1040
1146
|
node .MOP/scripts/mop-core.mjs agent route --actor CODE --task "task text"
|
|
1041
1147
|
node .MOP/scripts/mop-core.mjs agent list
|
|
1148
|
+
node .MOP/scripts/mop-core.mjs browser preflight
|
|
1042
1149
|
node .MOP/scripts/mop-core.mjs memory brief --actor CODE [--month YYYY-MM]
|
|
1043
1150
|
node .MOP/scripts/mop-core.mjs memory add --actor CODE --kind conversation --summary "what happened"
|
|
1044
1151
|
node .MOP/scripts/mop-core.mjs memory restore --actor CODE`);
|
package/.agents/AGENTS.md
CHANGED
|
@@ -23,6 +23,14 @@ Before doing anything, read `.MOP/STATE.json` and follow
|
|
|
23
23
|
`mop-core.mjs memory add --actor <codename> --kind conversation --summary "<outcome>"`.
|
|
24
24
|
- If the router says clarification is needed, ask the clarifying questions
|
|
25
25
|
before implementation.
|
|
26
|
+
- If the router returns `nextAction: "name-required-party-agents"`, ask every
|
|
27
|
+
question in `missingAgentQuestions` and stop until those agents are named.
|
|
28
|
+
- Before browser, scraping, extraction, click automation, login flow,
|
|
29
|
+
bot-detection, or form-filling work, run `mop-core.mjs browser preflight`. If
|
|
30
|
+
it reports Edge, Brave, or Opera, use browser-act `chrome-direct` mode and
|
|
31
|
+
guide the user to start remote debugging (`--remote-debugging-port`). If it
|
|
32
|
+
cannot detect a supported browser, ask which browser they use before doing
|
|
33
|
+
browser work.
|
|
26
34
|
- If the router activates Party Mode, show visible agent-to-agent dialogue using
|
|
27
35
|
the exact format in `.MOP/PROTOCOL.md`, with `PARTY MODE` shown in
|
|
28
36
|
large uppercase before the dialogue. Party Mode normally uses at least 3
|
package/AGENTS.md
CHANGED
|
@@ -31,7 +31,16 @@ follow `.MOP/PROTOCOL.md`.
|
|
|
31
31
|
|
|
32
32
|
- If the router marks the task as ambiguous, the named primary agent must ask
|
|
33
33
|
clarifying questions before implementation.
|
|
34
|
-
-
|
|
34
|
+
- If the router returns `nextAction: "name-required-party-agents"`, ask every
|
|
35
|
+
question in `missingAgentQuestions` and stop until those agents are named.
|
|
36
|
+
- **[browser] Agent Rule**: Before browser, scraping, extraction, click
|
|
37
|
+
automation, login flow, bot-detection, or form-filling work, run
|
|
38
|
+
`mop-core.mjs browser preflight`. It scans the default browser when possible.
|
|
39
|
+
If it reports Edge, Brave, or Opera, use browser-act `chrome-direct` mode and
|
|
40
|
+
guide the user to start remote debugging (`--remote-debugging-port`). If it
|
|
41
|
+
cannot detect a supported browser, ask which browser they use before doing
|
|
42
|
+
browser work. Never create a default Chrome session first when the user uses
|
|
43
|
+
another supported browser.
|
|
35
44
|
- If the router returns `partyMode.active: true`, use Party Mode. Show
|
|
36
45
|
`PARTY MODE` in large uppercase before the dialogue, then generate the
|
|
37
46
|
agent-to-agent and agent-to-user dialogue explicitly in your response using this exact format:
|
package/CLAUDE.md
CHANGED
|
@@ -23,6 +23,14 @@ follow `.MOP/PROTOCOL.md`.
|
|
|
23
23
|
`mop-core.mjs memory add --actor <codename> --kind conversation --summary "<one-line outcome>"`.
|
|
24
24
|
- If the router marks the task as ambiguous, the named primary agent must ask
|
|
25
25
|
clarifying questions before implementation.
|
|
26
|
+
- If the router returns `nextAction: "name-required-party-agents"`, ask every
|
|
27
|
+
question in `missingAgentQuestions` and stop until those agents are named.
|
|
28
|
+
- Before browser, scraping, extraction, click automation, login flow,
|
|
29
|
+
bot-detection, or form-filling work, run `mop-core.mjs browser preflight`. If
|
|
30
|
+
it reports Edge, Brave, or Opera, use browser-act `chrome-direct` mode and
|
|
31
|
+
guide the user to start remote debugging (`--remote-debugging-port`). If it
|
|
32
|
+
cannot detect a supported browser, ask which browser they use before doing
|
|
33
|
+
browser work.
|
|
26
34
|
- If the router returns `partyMode.active: true`, use Party Mode. Show
|
|
27
35
|
`PARTY MODE` in large uppercase before the dialogue, then show
|
|
28
36
|
agent-to-agent and agent-to-user dialogue with the exact format from
|
package/GEMINI.md
CHANGED
|
@@ -16,6 +16,11 @@ rules are imported below.
|
|
|
16
16
|
example: `agent: <agent-name> (<agent-role>) to <user>`.
|
|
17
17
|
- Save a one-line memory after meaningful work with
|
|
18
18
|
`mop-core.mjs memory add --actor <codename> --kind conversation --summary "<outcome>"`.
|
|
19
|
+
- If `agent route` returns `nextAction: "name-required-party-agents"`, ask every
|
|
20
|
+
question in `missingAgentQuestions` and stop until those agents are named.
|
|
21
|
+
- Before browser, scraping, extraction, click automation, login flow,
|
|
22
|
+
bot-detection, or form-filling work, run `mop-core.mjs browser preflight` and
|
|
23
|
+
follow its mode/question before doing browser work.
|
|
19
24
|
- Autosycn member commits must use the active member GitHub account. MOP derives
|
|
20
25
|
`ID+USERNAME@users.noreply.github.com` from `gh api user` by default and
|
|
21
26
|
refuses mismatched GitHub accounts.
|
package/README.bm.md
CHANGED
|
@@ -142,7 +142,7 @@ dan merge hanya bila workflow selamat.
|
|
|
142
142
|
| --- | --- |
|
|
143
143
|
| npm package | [`burhan-mop`](https://www.npmjs.com/package/burhan-mop) |
|
|
144
144
|
| command latest | `npx burhan-mop install` |
|
|
145
|
-
| GitHub release | [`v0.1.
|
|
145
|
+
| GitHub release | [`v0.1.8`](https://github.com/BURHANDEV-ENTERPRISE/BURHAN-MOP/releases/tag/v0.1.8) |
|
|
146
146
|
| Node | `>=20` |
|
|
147
147
|
|
|
148
148
|
## Links
|
package/README.md
CHANGED
|
@@ -141,7 +141,7 @@ and merges only when the workflow is safe.
|
|
|
141
141
|
| --- | --- |
|
|
142
142
|
| npm package | [`burhan-mop`](https://www.npmjs.com/package/burhan-mop) |
|
|
143
143
|
| latest command | `npx burhan-mop install` |
|
|
144
|
-
| GitHub release | [`v0.1.
|
|
144
|
+
| GitHub release | [`v0.1.8`](https://github.com/BURHANDEV-ENTERPRISE/BURHAN-MOP/releases/tag/v0.1.8) |
|
|
145
145
|
| Node | `>=20` |
|
|
146
146
|
|
|
147
147
|
## Links
|