opencode-writer-swarm 1.0.0 → 1.2.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/README.md +31 -0
- package/dist/commands/diagnose.d.ts +5 -0
- package/dist/commands/export.d.ts +5 -0
- package/dist/commands/index.d.ts +19 -0
- package/dist/commands/reset.d.ts +1 -0
- package/dist/config/schema.d.ts +66 -0
- package/dist/evidence/index.d.ts +1 -0
- package/dist/evidence/store.d.ts +42 -0
- package/dist/hooks/compaction-customizer.d.ts +11 -0
- package/dist/hooks/context-budget.d.ts +10 -0
- package/dist/hooks/extractors.d.ts +28 -3
- package/dist/hooks/guardrails.d.ts +22 -0
- package/dist/hooks/index.d.ts +3 -1
- package/dist/hooks/utils.d.ts +5 -29
- package/dist/index.d.ts +5 -4
- package/dist/index.js +11276 -288
- package/dist/plan/index.d.ts +2 -0
- package/dist/plan/manager.d.ts +63 -0
- package/dist/plan/schema.d.ts +160 -0
- package/dist/state.d.ts +44 -3
- package/dist/state.test.d.ts +1 -0
- package/dist/tools/file-manager.d.ts +7 -6
- package/package.json +7 -6
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type PlanDocument, type PlanPhase, type TaskStatus } from './schema';
|
|
2
|
+
/**
|
|
3
|
+
* Error thrown by PlanManager operations
|
|
4
|
+
*/
|
|
5
|
+
export declare class PlanManagerError extends Error {
|
|
6
|
+
code: string;
|
|
7
|
+
cause?: unknown | undefined;
|
|
8
|
+
constructor(message: string, code: string, cause?: unknown | undefined);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Interface for plan management operations
|
|
12
|
+
*/
|
|
13
|
+
export interface PlanManager {
|
|
14
|
+
/**
|
|
15
|
+
* Load and parse a plan from file (plan.md or plan.json)
|
|
16
|
+
* @param filePath - Path to plan file (optional, uses default discovery)
|
|
17
|
+
* @returns Parsed plan document
|
|
18
|
+
* @throws PlanManagerError if loading or parsing fails
|
|
19
|
+
*/
|
|
20
|
+
loadPlan(filePath?: string): Promise<PlanDocument>;
|
|
21
|
+
/**
|
|
22
|
+
* Get the current active phase
|
|
23
|
+
* @returns Current phase or null if no active phase
|
|
24
|
+
*/
|
|
25
|
+
getCurrentPhase(): PlanPhase | null;
|
|
26
|
+
/**
|
|
27
|
+
* Update the status of a specific task
|
|
28
|
+
* @param taskId - Task identifier
|
|
29
|
+
* @param status - New status value
|
|
30
|
+
* @returns true if update succeeded
|
|
31
|
+
* @throws PlanManagerError if task not found
|
|
32
|
+
*/
|
|
33
|
+
updateTaskStatus(taskId: string, status: TaskStatus): Promise<boolean>;
|
|
34
|
+
/**
|
|
35
|
+
* Get the resolved path to the plan file
|
|
36
|
+
* @returns Absolute path to plan file
|
|
37
|
+
*/
|
|
38
|
+
getPlanPath(): string;
|
|
39
|
+
/**
|
|
40
|
+
* Get the currently loaded plan document
|
|
41
|
+
* @returns Current plan or null if not loaded
|
|
42
|
+
*/
|
|
43
|
+
getPlan(): PlanDocument | null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Options for creating a PlanManager instance
|
|
47
|
+
*/
|
|
48
|
+
export interface PlanManagerOptions {
|
|
49
|
+
/** Base directory for plan discovery */
|
|
50
|
+
baseDir: string;
|
|
51
|
+
/** Default plan file name (default: 'plan.json') */
|
|
52
|
+
defaultPlanName?: string;
|
|
53
|
+
/** Whether to auto-discover plan.md if plan.json not found */
|
|
54
|
+
autoDiscoverMarkdown?: boolean;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Create a new PlanManager instance
|
|
58
|
+
*/
|
|
59
|
+
export declare function createPlanManager(options: PlanManagerOptions): PlanManager;
|
|
60
|
+
/**
|
|
61
|
+
* Load a plan document from file directly (convenience function)
|
|
62
|
+
*/
|
|
63
|
+
export declare function loadPlanDocument(filePath: string): Promise<PlanDocument>;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Task status values representing the lifecycle of a task
|
|
4
|
+
*/
|
|
5
|
+
export declare const TaskStatusSchema: z.ZodEnum<{
|
|
6
|
+
pending: "pending";
|
|
7
|
+
in_progress: "in_progress";
|
|
8
|
+
completed: "completed";
|
|
9
|
+
blocked: "blocked";
|
|
10
|
+
cancelled: "cancelled";
|
|
11
|
+
}>;
|
|
12
|
+
export type TaskStatus = z.infer<typeof TaskStatusSchema>;
|
|
13
|
+
/**
|
|
14
|
+
* Individual task within a phase
|
|
15
|
+
*/
|
|
16
|
+
export declare const PlanTaskSchema: z.ZodObject<{
|
|
17
|
+
id: z.ZodString;
|
|
18
|
+
title: z.ZodString;
|
|
19
|
+
description: z.ZodOptional<z.ZodString>;
|
|
20
|
+
status: z.ZodDefault<z.ZodEnum<{
|
|
21
|
+
pending: "pending";
|
|
22
|
+
in_progress: "in_progress";
|
|
23
|
+
completed: "completed";
|
|
24
|
+
blocked: "blocked";
|
|
25
|
+
cancelled: "cancelled";
|
|
26
|
+
}>>;
|
|
27
|
+
assignee: z.ZodOptional<z.ZodString>;
|
|
28
|
+
depends_on: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
29
|
+
acceptance_criteria: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
30
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
31
|
+
}, z.core.$strip>;
|
|
32
|
+
export type PlanTask = z.infer<typeof PlanTaskSchema>;
|
|
33
|
+
/**
|
|
34
|
+
* Phase status values
|
|
35
|
+
*/
|
|
36
|
+
export declare const PhaseStatusSchema: z.ZodEnum<{
|
|
37
|
+
pending: "pending";
|
|
38
|
+
in_progress: "in_progress";
|
|
39
|
+
completed: "completed";
|
|
40
|
+
blocked: "blocked";
|
|
41
|
+
}>;
|
|
42
|
+
export type PhaseStatus = z.infer<typeof PhaseStatusSchema>;
|
|
43
|
+
/**
|
|
44
|
+
* A phase containing multiple tasks
|
|
45
|
+
*/
|
|
46
|
+
export declare const PlanPhaseSchema: z.ZodObject<{
|
|
47
|
+
id: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
|
|
48
|
+
name: z.ZodString;
|
|
49
|
+
status: z.ZodDefault<z.ZodEnum<{
|
|
50
|
+
pending: "pending";
|
|
51
|
+
in_progress: "in_progress";
|
|
52
|
+
completed: "completed";
|
|
53
|
+
blocked: "blocked";
|
|
54
|
+
}>>;
|
|
55
|
+
tasks: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
56
|
+
id: z.ZodString;
|
|
57
|
+
title: z.ZodString;
|
|
58
|
+
description: z.ZodOptional<z.ZodString>;
|
|
59
|
+
status: z.ZodDefault<z.ZodEnum<{
|
|
60
|
+
pending: "pending";
|
|
61
|
+
in_progress: "in_progress";
|
|
62
|
+
completed: "completed";
|
|
63
|
+
blocked: "blocked";
|
|
64
|
+
cancelled: "cancelled";
|
|
65
|
+
}>>;
|
|
66
|
+
assignee: z.ZodOptional<z.ZodString>;
|
|
67
|
+
depends_on: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
68
|
+
acceptance_criteria: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
69
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
70
|
+
}, z.core.$strip>>>;
|
|
71
|
+
started_at: z.ZodOptional<z.ZodString>;
|
|
72
|
+
completed_at: z.ZodOptional<z.ZodString>;
|
|
73
|
+
}, z.core.$strip>;
|
|
74
|
+
export type PlanPhase = z.infer<typeof PlanPhaseSchema>;
|
|
75
|
+
/**
|
|
76
|
+
* Plan metadata for tracking and versioning
|
|
77
|
+
*/
|
|
78
|
+
export declare const PlanMetadataSchema: z.ZodObject<{
|
|
79
|
+
created_at: z.ZodOptional<z.ZodString>;
|
|
80
|
+
updated_at: z.ZodOptional<z.ZodString>;
|
|
81
|
+
version: z.ZodDefault<z.ZodString>;
|
|
82
|
+
author: z.ZodOptional<z.ZodString>;
|
|
83
|
+
swarm: z.ZodOptional<z.ZodString>;
|
|
84
|
+
migration_status: z.ZodOptional<z.ZodEnum<{
|
|
85
|
+
pending: "pending";
|
|
86
|
+
migrated: "migrated";
|
|
87
|
+
failed: "failed";
|
|
88
|
+
}>>;
|
|
89
|
+
}, z.core.$strip>;
|
|
90
|
+
export type PlanMetadata = z.infer<typeof PlanMetadataSchema>;
|
|
91
|
+
/**
|
|
92
|
+
* Main plan document schema supporting both JSON and Markdown-derived structures
|
|
93
|
+
*/
|
|
94
|
+
export declare const PlanDocumentSchema: z.ZodObject<{
|
|
95
|
+
schema_version: z.ZodDefault<z.ZodString>;
|
|
96
|
+
title: z.ZodString;
|
|
97
|
+
swarm: z.ZodOptional<z.ZodString>;
|
|
98
|
+
current_phase: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
99
|
+
phases: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
100
|
+
id: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
|
|
101
|
+
name: z.ZodString;
|
|
102
|
+
status: z.ZodDefault<z.ZodEnum<{
|
|
103
|
+
pending: "pending";
|
|
104
|
+
in_progress: "in_progress";
|
|
105
|
+
completed: "completed";
|
|
106
|
+
blocked: "blocked";
|
|
107
|
+
}>>;
|
|
108
|
+
tasks: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
109
|
+
id: z.ZodString;
|
|
110
|
+
title: z.ZodString;
|
|
111
|
+
description: z.ZodOptional<z.ZodString>;
|
|
112
|
+
status: z.ZodDefault<z.ZodEnum<{
|
|
113
|
+
pending: "pending";
|
|
114
|
+
in_progress: "in_progress";
|
|
115
|
+
completed: "completed";
|
|
116
|
+
blocked: "blocked";
|
|
117
|
+
cancelled: "cancelled";
|
|
118
|
+
}>>;
|
|
119
|
+
assignee: z.ZodOptional<z.ZodString>;
|
|
120
|
+
depends_on: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
121
|
+
acceptance_criteria: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
122
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
123
|
+
}, z.core.$strip>>>;
|
|
124
|
+
started_at: z.ZodOptional<z.ZodString>;
|
|
125
|
+
completed_at: z.ZodOptional<z.ZodString>;
|
|
126
|
+
}, z.core.$strip>>>;
|
|
127
|
+
metadata: z.ZodOptional<z.ZodObject<{
|
|
128
|
+
created_at: z.ZodOptional<z.ZodString>;
|
|
129
|
+
updated_at: z.ZodOptional<z.ZodString>;
|
|
130
|
+
version: z.ZodDefault<z.ZodString>;
|
|
131
|
+
author: z.ZodOptional<z.ZodString>;
|
|
132
|
+
swarm: z.ZodOptional<z.ZodString>;
|
|
133
|
+
migration_status: z.ZodOptional<z.ZodEnum<{
|
|
134
|
+
pending: "pending";
|
|
135
|
+
migrated: "migrated";
|
|
136
|
+
failed: "failed";
|
|
137
|
+
}>>;
|
|
138
|
+
}, z.core.$strip>>;
|
|
139
|
+
}, z.core.$strip>;
|
|
140
|
+
export type PlanDocument = z.infer<typeof PlanDocumentSchema>;
|
|
141
|
+
/**
|
|
142
|
+
* Validation result for plan documents
|
|
143
|
+
*/
|
|
144
|
+
export interface PlanValidationResult {
|
|
145
|
+
valid: boolean;
|
|
146
|
+
errors: z.ZodError | null;
|
|
147
|
+
data?: PlanDocument;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Validate a plan document against the schema
|
|
151
|
+
*/
|
|
152
|
+
export declare function validatePlanDocument(data: unknown): PlanValidationResult;
|
|
153
|
+
/**
|
|
154
|
+
* Default empty plan document
|
|
155
|
+
*/
|
|
156
|
+
export declare function createEmptyPlan(title?: string): PlanDocument;
|
|
157
|
+
/**
|
|
158
|
+
* Get default values for plan metadata
|
|
159
|
+
*/
|
|
160
|
+
export declare function getPlanMetadataDefaults(): PlanMetadata;
|
package/dist/state.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*/
|
|
1
|
+
import type { PluginConfig } from './config/schema';
|
|
2
|
+
/** Shared state for plugin sessions and cache tracking. */
|
|
4
3
|
export interface DelegationEntry {
|
|
5
4
|
from: string;
|
|
6
5
|
to: string;
|
|
@@ -11,6 +10,16 @@ export interface CacheStats {
|
|
|
11
10
|
cacheMisses: number;
|
|
12
11
|
cacheSizeBytes: number;
|
|
13
12
|
}
|
|
13
|
+
/** Guardrail tracking state per session */
|
|
14
|
+
export interface GuardrailSession {
|
|
15
|
+
toolCalls: number;
|
|
16
|
+
firstToolAt: number | null;
|
|
17
|
+
repetitionCount: number;
|
|
18
|
+
consecutiveErrors: number;
|
|
19
|
+
lastTool: string | null;
|
|
20
|
+
}
|
|
21
|
+
/** Maximum number of sessions to track before pruning */
|
|
22
|
+
export declare const MAX_SESSIONS = 1000;
|
|
14
23
|
export declare const swarmState: {
|
|
15
24
|
/** Active agent per session — keyed by sessionID */
|
|
16
25
|
activeAgent: Map<string, string>;
|
|
@@ -20,5 +29,37 @@ export declare const swarmState: {
|
|
|
20
29
|
pendingEvents: number;
|
|
21
30
|
/** Cache statistics for markdown AST parsing */
|
|
22
31
|
cacheStats: CacheStats;
|
|
32
|
+
/** Last successfully loaded config document */
|
|
33
|
+
lastValidConfig: PluginConfig | null;
|
|
34
|
+
/** Guardrail tracking per session — keyed by sessionID */
|
|
35
|
+
guardrails: Map<string, GuardrailSession>;
|
|
23
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* Prune the oldest sessions from both Maps.
|
|
39
|
+
* Map iteration order is insertion order, so the first entries are oldest.
|
|
40
|
+
* @param count - Number of sessions to prune
|
|
41
|
+
*/
|
|
42
|
+
export declare function pruneOldestSessions(count: number): void;
|
|
43
|
+
/**
|
|
44
|
+
* Enforce the session limit by pruning if Maps exceed MAX_SESSIONS.
|
|
45
|
+
* Prunes 10% of sessions when the limit is hit.
|
|
46
|
+
*/
|
|
47
|
+
export declare function enforceSessionLimit(): void;
|
|
48
|
+
/** Clear all session tracking, events, and cache stats. Used between tests and for plugin reinitialization. */
|
|
24
49
|
export declare function resetSwarmState(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Finalize and clear all swarm state.
|
|
52
|
+
* Alias for resetSwarmState, signaling end-of-lifecycle cleanup.
|
|
53
|
+
*/
|
|
54
|
+
export declare function disposeSwarmState(): void;
|
|
55
|
+
/**
|
|
56
|
+
* Get or initialize guardrail session state for a given sessionID.
|
|
57
|
+
* @param sessionID - The session identifier
|
|
58
|
+
* @returns The guardrail session state (initializes if missing)
|
|
59
|
+
*/
|
|
60
|
+
export declare function getGuardrailSession(sessionID: string): GuardrailSession;
|
|
61
|
+
/**
|
|
62
|
+
* Reset guardrail state for a specific session.
|
|
63
|
+
* @param sessionID - The session identifier to clear
|
|
64
|
+
*/
|
|
65
|
+
export declare function resetGuardrailState(sessionID: string): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as fs from 'node:fs/promises';
|
|
2
2
|
import { type ToolDefinition } from '@opencode-ai/plugin/tool';
|
|
3
3
|
import { MAX_FILE_SIZE, MAX_DIRECTORY_DEPTH } from '../config/constants';
|
|
4
|
+
import { type PluginConfig } from '../config/schema';
|
|
4
5
|
/**
|
|
5
6
|
* Sleep for a given number of milliseconds
|
|
6
7
|
*/
|
|
@@ -21,15 +22,15 @@ export declare function writeFileWithRetry(filePath: string, content: string, op
|
|
|
21
22
|
encoding: BufferEncoding;
|
|
22
23
|
}, writeFn?: typeof fs.writeFile, retryEnabled?: boolean, maxRetries?: number): Promise<void>;
|
|
23
24
|
/**
|
|
24
|
-
*
|
|
25
|
+
* Create a tool to read a file from the .writer/ directory.
|
|
25
26
|
*/
|
|
26
|
-
export declare
|
|
27
|
+
export declare function createReadWriterFile(directory: string): ToolDefinition;
|
|
27
28
|
/**
|
|
28
|
-
*
|
|
29
|
+
* Create a tool to write content to a file in the .writer/ directory. Overwrites if exists.
|
|
29
30
|
*/
|
|
30
|
-
export declare
|
|
31
|
+
export declare function createWriteWriterFile(directory: string, config?: PluginConfig): ToolDefinition;
|
|
31
32
|
/**
|
|
32
|
-
*
|
|
33
|
+
* Create a tool to list all files in the .writer/ directory recursively.
|
|
33
34
|
*/
|
|
34
|
-
export declare
|
|
35
|
+
export declare function createListWriterFiles(directory: string): ToolDefinition;
|
|
35
36
|
export { MAX_FILE_SIZE, MAX_DIRECTORY_DEPTH };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
"name": "opencode-writer-swarm",
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Editorial swarm plugin for OpenCode - professional writing workflow with editor-in-chief, writers, and reviewers",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -39,14 +39,15 @@
|
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@opencode-ai/plugin": "^1.1.53",
|
|
41
41
|
"@opencode-ai/sdk": "^1.1.53",
|
|
42
|
+
"mdast-util-from-markdown": "^2.0.2",
|
|
43
|
+
"mdast-util-gfm": "^3.1.0",
|
|
42
44
|
"micromark-extension-gfm": "^3.0.0",
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"mdast-util-gfm": "^1.0.0",
|
|
46
|
-
"unist-util-visit": "^4.1.0"
|
|
45
|
+
"unist-util-visit": "^5.1.0",
|
|
46
|
+
"zod": "^4.1.8"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@biomejs/biome": "2.3.14",
|
|
50
|
+
"@types/mdast": "^4.0.4",
|
|
50
51
|
"bun-types": "latest",
|
|
51
52
|
"typescript": "^5.7.3"
|
|
52
53
|
}
|