shraga 0.1.160 → 0.1.161
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/dist/client/index.html
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
14
14
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
15
15
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet" />
|
|
16
|
-
<script type="module" crossorigin src="/assets/index-
|
|
16
|
+
<script type="module" crossorigin src="/assets/index-C46Azkf_.js"></script>
|
|
17
17
|
<link rel="stylesheet" crossorigin href="/assets/index-NtN1I_dh.css">
|
|
18
18
|
</head>
|
|
19
19
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shraga",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.161",
|
|
4
4
|
"description": "The teammate you delegate coding to — a self-hostable, multi-user AI coding agent web UI (Claude Code, with a pluggable engine seam).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
package/src/server/claude.ts
CHANGED
|
@@ -313,6 +313,11 @@ async function* runTurn(opts: StreamChatOpts, guard?: TurnGuard): AsyncGenerator
|
|
|
313
313
|
|
|
314
314
|
const sessionMeta = opts.sessionId ? getSession(opts.sessionId) : undefined;
|
|
315
315
|
const directives: Directives = { ...sessionMeta?.directives, ...parsed };
|
|
316
|
+
// A two-model mode (delegate/advisor) is sticky like the model: `[off]` clears it, and a new mode
|
|
317
|
+
// replaces the other one. `modeOff` is a command, not a setting — never stored.
|
|
318
|
+
if (parsed.modeOff || parsed.advisor) delete directives.delegate;
|
|
319
|
+
if (parsed.modeOff || parsed.delegate) delete directives.advisor;
|
|
320
|
+
delete directives.modeOff;
|
|
316
321
|
// Persist ONLY what was explicitly chosen (inline directives, or the Agent Config panel's
|
|
317
322
|
// per-conversation save). Gaps stay gaps: every engine resolves `directives.x ?? config.x` at
|
|
318
323
|
// send time, so the global agent-config keeps applying live to sessions nobody pinned —
|
package/src/server/directives.ts
CHANGED
|
@@ -6,6 +6,12 @@ export interface Directives {
|
|
|
6
6
|
engine?: string;
|
|
7
7
|
/** claude-code SDK session resume for this conversation (overrides agent-config `sdkResume`). */
|
|
8
8
|
resume?: boolean;
|
|
9
|
+
/** agentx DELEGATE mode `[planner->worker]` (key `delegate`): the worker model; `model` (left side) plans. */
|
|
10
|
+
delegate?: string;
|
|
11
|
+
/** agentx ADVISOR mode `[worker<-advisor]` (key `advisor`): the advisor model; `model` (left side) works. */
|
|
12
|
+
advisor?: string;
|
|
13
|
+
/** `[off]` / `[mode:off]`: clears a sticky delegate/advisor mode. Consumed by streamChat, never stored. */
|
|
14
|
+
modeOff?: boolean;
|
|
9
15
|
}
|
|
10
16
|
|
|
11
17
|
export interface ParsedPrompt {
|
|
@@ -28,7 +34,15 @@ import { MODEL_ALIASES } from './model-aliases.ts';
|
|
|
28
34
|
|
|
29
35
|
const DIRECTIVE_RE = /^\s*\[([^\]]*)\]\s*([\s\S]*)/;
|
|
30
36
|
|
|
31
|
-
const DIRECTIVE_KEYS = ['model', 'turns', 'thinking', 'think', 'effort', 'engine', 'resume'];
|
|
37
|
+
const DIRECTIVE_KEYS = ['model', 'turns', 'thinking', 'think', 'effort', 'engine', 'resume', 'delegate', 'advisor', 'mode'];
|
|
38
|
+
|
|
39
|
+
/** `a->b` (delegate) / `a<-b` (advisor) — agentx's two-model mode grammar; the left side may be empty. */
|
|
40
|
+
function splitModePair(token: string): { left: string; op: '->' | '<-'; right: string } | null {
|
|
41
|
+
const i = token.search(/->|<-/);
|
|
42
|
+
if (i === -1) return null;
|
|
43
|
+
const right = token.slice(i + 2).trim();
|
|
44
|
+
return right ? { left: token.slice(0, i).trim(), op: token.slice(i, i + 2) as '->' | '<-', right } : null;
|
|
45
|
+
}
|
|
32
46
|
|
|
33
47
|
/** MODEL_ALIASES only covers the bare Anthropic shorthands. A `provider/model` id
|
|
34
48
|
* (`cursor/composer-2.5`, `openai/gpt-5.6`) is already concrete — gating it on the alias table
|
|
@@ -72,6 +86,9 @@ export function isDirectiveGroup(raw: string): boolean {
|
|
|
72
86
|
const colonIdx = t.indexOf(':');
|
|
73
87
|
if (colonIdx !== -1) return DIRECTIVE_KEYS.includes(t.slice(0, colonIdx).trim().toLowerCase());
|
|
74
88
|
const v = t.toLowerCase();
|
|
89
|
+
const pair = splitModePair(v);
|
|
90
|
+
if (pair) return (!pair.left || !!resolveModelAlias(pair.left)) && !!resolveModelAlias(pair.right);
|
|
91
|
+
if (v === 'off') return true;
|
|
75
92
|
return !!MODEL_ALIASES[v] || !!modelResolver?.(v) || /^\d+$/.test(v) || ['think', 'adaptive', 'nothink', 'nothinking'].includes(v);
|
|
76
93
|
});
|
|
77
94
|
}
|
|
@@ -132,6 +149,17 @@ export function parseDirectives(text: string): ParsedPrompt {
|
|
|
132
149
|
unresolvedModel = applyDirective(directives, key, val) ?? unresolvedModel;
|
|
133
150
|
} else {
|
|
134
151
|
const val = t.toLowerCase();
|
|
152
|
+
const pair = splitModePair(val);
|
|
153
|
+
if (pair) {
|
|
154
|
+
// Both sides must resolve: a half-resolved pair would silently run a mode on the wrong model.
|
|
155
|
+
const worker = resolveModelAlias(pair.right);
|
|
156
|
+
if (worker && (!pair.left || resolveModelToken(directives, pair.left))) {
|
|
157
|
+
if (pair.op === '->') directives.delegate = worker.model; else directives.advisor = worker.model;
|
|
158
|
+
} else unresolvedModel ??= t;
|
|
159
|
+
positionalIndex++;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (val === 'off') { directives.modeOff = true; positionalIndex++; continue; }
|
|
135
163
|
if (positionalIndex === 0 && resolveModelToken(directives, val)) {
|
|
136
164
|
// handled
|
|
137
165
|
} else if (positionalIndex <= 1 && /^\d+$/.test(val)) {
|
|
@@ -179,6 +207,18 @@ function applyDirective(d: Directives, key: string, val: string): string | undef
|
|
|
179
207
|
case 'engine':
|
|
180
208
|
d.engine = val;
|
|
181
209
|
break;
|
|
210
|
+
case 'delegate':
|
|
211
|
+
case 'advisor': {
|
|
212
|
+
const hit = resolveModelAlias(val);
|
|
213
|
+
if (hit) d[key] = hit.model;
|
|
214
|
+
else if (isQualifiedModel(val)) d[key] = val;
|
|
215
|
+
else return val;
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
case 'mode':
|
|
219
|
+
if (val === 'off') d.modeOff = true;
|
|
220
|
+
else console.warn(`[directives] Invalid mode value: "${val}"`);
|
|
221
|
+
break;
|
|
182
222
|
case 'resume':
|
|
183
223
|
if (['on', 'true', '1'].includes(val)) d.resume = true;
|
|
184
224
|
else if (['off', 'false', '0'].includes(val)) d.resume = false;
|