opencode-ultra 0.9.6 → 0.9.7
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/hooks/comment-checker.d.ts +1 -1
- package/dist/hooks/token-truncation.d.ts +2 -2
- package/dist/index.js +14 -11
- package/dist/safety/sanitizer.d.ts +2 -2
- package/dist/threadweaver/complexity-router.d.ts +35 -0
- package/dist/threadweaver/index.d.ts +9 -0
- package/dist/threadweaver/prompts.d.ts +25 -0
- package/dist/threadweaver/protocol.d.ts +17 -0
- package/dist/threadweaver/roles.d.ts +15 -0
- package/dist/threadweaver/threadweaver-tool.d.ts +9 -0
- package/dist/threadweaver/types.d.ts +81 -0
- package/dist/threadweaver/weighting.d.ts +36 -0
- package/package.json +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export declare function truncateMiddle(input:
|
|
1
|
+
export declare function truncateMiddle(input: unknown, maxChars: number): string;
|
|
2
2
|
export declare function createTokenTruncationHook(internalSessions: Set<string>, maxChars?: number): (input: {
|
|
3
3
|
tool: string | {
|
|
4
4
|
name: string;
|
|
5
5
|
};
|
|
6
6
|
sessionID: string;
|
|
7
7
|
}, output: {
|
|
8
|
-
output:
|
|
8
|
+
output: unknown;
|
|
9
9
|
}) => void;
|
package/dist/index.js
CHANGED
|
@@ -27942,7 +27942,8 @@ var INJECTION_PATTERNS = [
|
|
|
27942
27942
|
{ pattern: /(?:\u65B0\u3057\u3044|\u66F4\u65B0\u3055\u308C\u305F)\u6307\u793A\s*[:\uFF1A]/i, label: "new-instructions-ja" }
|
|
27943
27943
|
];
|
|
27944
27944
|
var SUSPICIOUS_UNICODE = /[\u200B-\u200F\u202A-\u202E\u2060-\u2069\uFEFF\u00AD]/g;
|
|
27945
|
-
function sanitizeAgentOutput(
|
|
27945
|
+
function sanitizeAgentOutput(input) {
|
|
27946
|
+
let text = typeof input === "string" ? input : JSON.stringify(input) ?? "";
|
|
27946
27947
|
const warnings = [];
|
|
27947
27948
|
const invisibleCount = (text.match(SUSPICIOUS_UNICODE) || []).length;
|
|
27948
27949
|
if (invisibleCount > 0) {
|
|
@@ -28277,7 +28278,7 @@ async function runAgent(ctx, task, toolCtx, internalSessions, resilience, provid
|
|
|
28277
28278
|
}), { maxAttempts: 3 });
|
|
28278
28279
|
const messages = messagesResp.data ?? [];
|
|
28279
28280
|
const lastAssistant = messages.filter((m) => m.info?.role === "assistant").pop();
|
|
28280
|
-
const rawResult = lastAssistant?.parts?.filter((p) => p.type === "text" && p.text).map((p) => p.text).join(`
|
|
28281
|
+
const rawResult = lastAssistant?.parts?.filter((p) => p.type === "text" && p.text).map((p) => typeof p.text === "string" ? p.text : JSON.stringify(p.text)).join(`
|
|
28281
28282
|
`) ?? "(No response from agent)";
|
|
28282
28283
|
internalSessions.delete(id);
|
|
28283
28284
|
await ctx.client.session.delete({ path: { id }, query: { directory: ctx.directory } }).catch(() => {});
|
|
@@ -30534,7 +30535,8 @@ function createCommentCheckerHook(internalSessions, maxRatio = 0.3, slopThreshol
|
|
|
30534
30535
|
const content = fs12.readFileSync(filePath, "utf-8");
|
|
30535
30536
|
const result = checkComments(content, filePath, maxRatio, slopThreshold);
|
|
30536
30537
|
if (result.shouldWarn) {
|
|
30537
|
-
output.output
|
|
30538
|
+
const current = typeof output.output === "string" ? output.output : JSON.stringify(output.output) ?? "";
|
|
30539
|
+
output.output = current + `
|
|
30538
30540
|
|
|
30539
30541
|
[Comment Checker] ${result.message}`;
|
|
30540
30542
|
log(`Comment Checker warning: ${filePath}`, {
|
|
@@ -30549,13 +30551,14 @@ function createCommentCheckerHook(internalSessions, maxRatio = 0.3, slopThreshol
|
|
|
30549
30551
|
// src/hooks/token-truncation.ts
|
|
30550
30552
|
var DEFAULT_MAX_CHARS = 30000;
|
|
30551
30553
|
function truncateMiddle(input, maxChars) {
|
|
30554
|
+
const text = typeof input === "string" ? input : JSON.stringify(input) ?? "";
|
|
30552
30555
|
if (!Number.isFinite(maxChars) || maxChars <= 0)
|
|
30553
|
-
return
|
|
30554
|
-
if (
|
|
30555
|
-
return
|
|
30556
|
+
return text;
|
|
30557
|
+
if (text.length <= maxChars)
|
|
30558
|
+
return text;
|
|
30556
30559
|
if (maxChars < 32)
|
|
30557
|
-
return
|
|
30558
|
-
const len =
|
|
30560
|
+
return text.slice(0, maxChars);
|
|
30561
|
+
const len = text.length;
|
|
30559
30562
|
let head = Math.floor(maxChars * 0.4);
|
|
30560
30563
|
let tail = Math.floor(maxChars * 0.4);
|
|
30561
30564
|
head = Math.min(Math.max(head, 1), maxChars);
|
|
@@ -30577,9 +30580,9 @@ function truncateMiddle(input, maxChars) {
|
|
|
30577
30580
|
const marker22 = buildMarker(removed22);
|
|
30578
30581
|
const budget = h + marker22.length + finalTail2;
|
|
30579
30582
|
if (budget > maxChars) {
|
|
30580
|
-
return
|
|
30583
|
+
return text.slice(0, maxChars);
|
|
30581
30584
|
}
|
|
30582
|
-
return
|
|
30585
|
+
return text.slice(0, h) + marker22 + text.slice(len - finalTail2);
|
|
30583
30586
|
};
|
|
30584
30587
|
const removed = Math.max(0, len - head - tail);
|
|
30585
30588
|
const marker = buildMarker(removed);
|
|
@@ -30596,7 +30599,7 @@ function createTokenTruncationHook(internalSessions, maxChars = DEFAULT_MAX_CHAR
|
|
|
30596
30599
|
return (input, output) => {
|
|
30597
30600
|
if (internalSessions.has(input.sessionID))
|
|
30598
30601
|
return;
|
|
30599
|
-
const before = output.output;
|
|
30602
|
+
const before = typeof output.output === "string" ? output.output : JSON.stringify(output.output) ?? "";
|
|
30600
30603
|
const after = truncateMiddle(before, budget);
|
|
30601
30604
|
if (after !== before) {
|
|
30602
30605
|
output.output = after;
|
|
@@ -11,9 +11,9 @@ export interface SanitizeResult {
|
|
|
11
11
|
* Sanitize text from agent outputs to prevent prompt injection.
|
|
12
12
|
* Returns the cleaned text plus any warnings.
|
|
13
13
|
*/
|
|
14
|
-
export declare function sanitizeAgentOutput(
|
|
14
|
+
export declare function sanitizeAgentOutput(input: unknown): SanitizeResult;
|
|
15
15
|
/**
|
|
16
16
|
* Apply sanitizer to a spawn_agent result string.
|
|
17
17
|
* Adds a warning banner if injection was detected.
|
|
18
18
|
*/
|
|
19
|
-
export declare function sanitizeSpawnResult(result:
|
|
19
|
+
export declare function sanitizeSpawnResult(result: unknown): string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThreadWeaver — Complexity Router
|
|
3
|
+
* Determines standard/heavy mode and sparse-activates relevant agents.
|
|
4
|
+
*/
|
|
5
|
+
import type { AgentRole, ComplexityAnalysis, ThreadWeaverConfig } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* Compute complexity score (0-11).
|
|
8
|
+
*
|
|
9
|
+
* Token score: 0-3
|
|
10
|
+
* Domain score: 0-3
|
|
11
|
+
* Heavy signal score: 0-3
|
|
12
|
+
* Question score: 0-2
|
|
13
|
+
*/
|
|
14
|
+
export declare function computeComplexityScore(query: string): {
|
|
15
|
+
score: number;
|
|
16
|
+
tokens: number;
|
|
17
|
+
domainCount: number;
|
|
18
|
+
matchedDomains: string[];
|
|
19
|
+
heavySignals: number;
|
|
20
|
+
questions: number;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Compute domain relevance score for a specialist agent against the query.
|
|
24
|
+
* Returns 0.0-1.0 indicating how relevant this agent is.
|
|
25
|
+
*/
|
|
26
|
+
export declare function computeDomainRelevance(agent: AgentRole, query: string): number;
|
|
27
|
+
/**
|
|
28
|
+
* Sparse-activate specialist agents based on query domain relevance.
|
|
29
|
+
* Returns only specialists above the activation threshold.
|
|
30
|
+
*/
|
|
31
|
+
export declare function sparseActivate(query: string, threshold: number): AgentRole[];
|
|
32
|
+
/**
|
|
33
|
+
* Route complexity and select activated agents.
|
|
34
|
+
*/
|
|
35
|
+
export declare function routeComplexity(query: string, config: ThreadWeaverConfig): ComplexityAnalysis;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThreadWeaver — Public Exports
|
|
3
|
+
*/
|
|
4
|
+
export { createThreadWeaverTool } from "./threadweaver-tool";
|
|
5
|
+
export { runThreadWeaver, type ThreadWeaverDeps } from "./protocol";
|
|
6
|
+
export { routeComplexity, computeComplexityScore, computeDomainRelevance, sparseActivate } from "./complexity-router";
|
|
7
|
+
export { computeDynamicWeights, extractConfidence, parseCritiques, computeCrossAgreement } from "./weighting";
|
|
8
|
+
export { CORE_ROLES, SPECIALIST_ROLES, ALL_ROLES, getCoreRoles, getAllRoles, findRole } from "./roles";
|
|
9
|
+
export { type ThreadWeaverConfig, type ThreadWeaverResult, type ComplexityLevel, type ComplexityAnalysis, type AgentRole, type AgentOutput, type AgentWeight, type Critique, type Dissent, type RoundResult, type RoundType, DEFAULT_THREADWEAVER_CONFIG, } from "./types";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThreadWeaver — Prompt Templates
|
|
3
|
+
* Structured prompts for each round of the debate protocol.
|
|
4
|
+
*/
|
|
5
|
+
import type { AgentRole, AgentOutput, Critique } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* Build the analysis prompt for Round 1 (parallel initial analysis).
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildAnalysisPrompt(role: AgentRole, query: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Build the cross-critique prompt for Round 2.
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildCritiquePrompt(role: AgentRole, query: string, round1Outputs: AgentOutput[]): string;
|
|
14
|
+
/**
|
|
15
|
+
* Build the revision prompt for Round 3.
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildRevisionPrompt(role: AgentRole, query: string, ownRound1Output: AgentOutput, critiquesOfMe: Critique[]): string;
|
|
18
|
+
/**
|
|
19
|
+
* Build the synthesis prompt for the Captain (final round).
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildSynthesisPrompt(query: string, round3Outputs: AgentOutput[], weights: Array<{
|
|
22
|
+
agentId: string;
|
|
23
|
+
role: string;
|
|
24
|
+
finalWeight: number;
|
|
25
|
+
}>): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThreadWeaver — Debate Protocol
|
|
3
|
+
* Orchestrates the 3-round debate loop with parallel agent execution.
|
|
4
|
+
*/
|
|
5
|
+
import type { PluginInput, ToolContext } from "@opencode-ai/plugin";
|
|
6
|
+
import { ProviderResilience } from "../shared";
|
|
7
|
+
import type { ConcurrencyPool } from "../concurrency";
|
|
8
|
+
import type { ThreadWeaverConfig, ThreadWeaverResult } from "./types";
|
|
9
|
+
export interface ThreadWeaverDeps {
|
|
10
|
+
pool?: ConcurrencyPool;
|
|
11
|
+
resilience?: ProviderResilience;
|
|
12
|
+
internalSessions: Set<string>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Main entry point: Run the ThreadWeaver debate protocol.
|
|
16
|
+
*/
|
|
17
|
+
export declare function runThreadWeaver(ctx: PluginInput, query: string, userConfig: Partial<ThreadWeaverConfig>, deps: ThreadWeaverDeps, toolCtx: ToolContext): Promise<ThreadWeaverResult>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThreadWeaver — Agent Role Definitions
|
|
3
|
+
* Standard (4 core) + Heavy (16 = 4 core + 12 specialists)
|
|
4
|
+
*/
|
|
5
|
+
import type { AgentRole } from "./types";
|
|
6
|
+
export declare const CORE_ROLES: AgentRole[];
|
|
7
|
+
export declare const SPECIALIST_ROLES: AgentRole[];
|
|
8
|
+
/** All 16 roles (4 core + 12 specialists) */
|
|
9
|
+
export declare const ALL_ROLES: AgentRole[];
|
|
10
|
+
/** Get core roles only (standard mode) */
|
|
11
|
+
export declare function getCoreRoles(): AgentRole[];
|
|
12
|
+
/** Get all roles (heavy mode) */
|
|
13
|
+
export declare function getAllRoles(): AgentRole[];
|
|
14
|
+
/** Find a role by ID */
|
|
15
|
+
export declare function findRole(id: string): AgentRole | undefined;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThreadWeaver — Tool Registration
|
|
3
|
+
* Registers the threadweaver tool with the OpenCode plugin system.
|
|
4
|
+
*/
|
|
5
|
+
import type { PluginInput } from "@opencode-ai/plugin";
|
|
6
|
+
import { tool } from "@opencode-ai/plugin";
|
|
7
|
+
import type { ThreadWeaverConfig } from "./types";
|
|
8
|
+
import { type ThreadWeaverDeps } from "./protocol";
|
|
9
|
+
export declare function createThreadWeaverTool(ctx: PluginInput, twConfig: Partial<ThreadWeaverConfig>, deps: ThreadWeaverDeps): ReturnType<typeof tool>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThreadWeaver — Multi-Agent Debate Protocol
|
|
3
|
+
* All TypeScript type definitions.
|
|
4
|
+
*/
|
|
5
|
+
export type ComplexityLevel = "standard" | "heavy";
|
|
6
|
+
export interface ThreadWeaverConfig {
|
|
7
|
+
debateRounds: number;
|
|
8
|
+
heavyThreshold: number;
|
|
9
|
+
forceComplexity: ComplexityLevel | null;
|
|
10
|
+
model: string | null;
|
|
11
|
+
activationThreshold: number;
|
|
12
|
+
roundTimeoutMs: number;
|
|
13
|
+
totalTimeoutMs: number;
|
|
14
|
+
saveLedger: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare const DEFAULT_THREADWEAVER_CONFIG: ThreadWeaverConfig;
|
|
17
|
+
export interface AgentRole {
|
|
18
|
+
id: string;
|
|
19
|
+
role: string;
|
|
20
|
+
grokEquiv: string;
|
|
21
|
+
focus: string;
|
|
22
|
+
/** Domain keywords for sparse activation relevance scoring */
|
|
23
|
+
domains: string[];
|
|
24
|
+
/** For specialist agents, reference to the core role they extend */
|
|
25
|
+
parentRole?: string;
|
|
26
|
+
}
|
|
27
|
+
export type RoundType = "analysis" | "critique" | "revision";
|
|
28
|
+
export interface AgentOutput {
|
|
29
|
+
agentId: string;
|
|
30
|
+
role: string;
|
|
31
|
+
content: string;
|
|
32
|
+
selfConfidence: number;
|
|
33
|
+
durationMs: number;
|
|
34
|
+
error?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface Critique {
|
|
37
|
+
criticId: string;
|
|
38
|
+
targetId: string;
|
|
39
|
+
/** -1 (disagree), 0 (neutral), 1 (agree) */
|
|
40
|
+
agreement: number;
|
|
41
|
+
issues: string[];
|
|
42
|
+
strengths: string[];
|
|
43
|
+
}
|
|
44
|
+
export interface RoundResult {
|
|
45
|
+
roundNumber: number;
|
|
46
|
+
roundType: RoundType;
|
|
47
|
+
outputs: AgentOutput[];
|
|
48
|
+
critiques?: Critique[];
|
|
49
|
+
durationMs: number;
|
|
50
|
+
}
|
|
51
|
+
export interface AgentWeight {
|
|
52
|
+
agentId: string;
|
|
53
|
+
role: string;
|
|
54
|
+
selfConfidence: number;
|
|
55
|
+
crossAgreement: number;
|
|
56
|
+
domainRelevance: number;
|
|
57
|
+
finalWeight: number;
|
|
58
|
+
}
|
|
59
|
+
export interface Dissent {
|
|
60
|
+
topic: string;
|
|
61
|
+
positions: Array<{
|
|
62
|
+
agentId: string;
|
|
63
|
+
position: string;
|
|
64
|
+
}>;
|
|
65
|
+
}
|
|
66
|
+
export interface ThreadWeaverResult {
|
|
67
|
+
query: string;
|
|
68
|
+
complexity: ComplexityLevel;
|
|
69
|
+
activatedAgents: string[];
|
|
70
|
+
rounds: RoundResult[];
|
|
71
|
+
weights: AgentWeight[];
|
|
72
|
+
synthesis: string;
|
|
73
|
+
dissents: Dissent[];
|
|
74
|
+
totalDurationMs: number;
|
|
75
|
+
partial?: boolean;
|
|
76
|
+
}
|
|
77
|
+
export interface ComplexityAnalysis {
|
|
78
|
+
level: ComplexityLevel;
|
|
79
|
+
score: number;
|
|
80
|
+
activatedAgents: AgentRole[];
|
|
81
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThreadWeaver — Dynamic Weighting
|
|
3
|
+
* Computes final weights from self-confidence, cross-agreement, and domain relevance.
|
|
4
|
+
*/
|
|
5
|
+
import type { AgentOutput, AgentWeight, Critique, AgentRole } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* Extract self-reported confidence from agent output.
|
|
8
|
+
* Looks for "Confidence: X/10" pattern at end of content.
|
|
9
|
+
* Returns 0.0-1.0 (normalized from 0-10 scale).
|
|
10
|
+
* Default: 0.5 if not found.
|
|
11
|
+
*/
|
|
12
|
+
export declare function extractConfidence(content: string): number;
|
|
13
|
+
/**
|
|
14
|
+
* Parse critique blocks from an agent's round-2 output.
|
|
15
|
+
*
|
|
16
|
+
* Expected format:
|
|
17
|
+
* ## Re: [agent-id]
|
|
18
|
+
* Agreement: 1 (or 0, -1)
|
|
19
|
+
* Issues: ...
|
|
20
|
+
* Strengths: ...
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseCritiques(criticId: string, content: string): Critique[];
|
|
23
|
+
/**
|
|
24
|
+
* Compute cross-agreement score for an agent.
|
|
25
|
+
* Average of all agreement values from other agents, normalized to 0-1.
|
|
26
|
+
* agreement: -1 → 0.0, 0 → 0.5, 1 → 1.0
|
|
27
|
+
*/
|
|
28
|
+
export declare function computeCrossAgreement(agentId: string, allCritiques: Critique[]): number;
|
|
29
|
+
/**
|
|
30
|
+
* Compute dynamic weights for all agents after all rounds.
|
|
31
|
+
*
|
|
32
|
+
* Formula:
|
|
33
|
+
* raw_weight = (selfConfidence * 0.25) + (crossAgreement * 0.45) + (domainRelevance * 0.30)
|
|
34
|
+
* final_weight = raw_weight / sum(all_raw_weights)
|
|
35
|
+
*/
|
|
36
|
+
export declare function computeDynamicWeights(outputs: AgentOutput[], allCritiques: Critique[], activatedRoles: AgentRole[], query: string): AgentWeight[];
|