@agent-workspace/utils 0.5.0
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 +80 -0
- package/dist/frontmatter.d.ts +30 -0
- package/dist/frontmatter.d.ts.map +1 -0
- package/dist/frontmatter.js +46 -0
- package/dist/frontmatter.js.map +1 -0
- package/dist/graph.d.ts +109 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +252 -0
- package/dist/graph.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/reputation.d.ts +37 -0
- package/dist/reputation.d.ts.map +1 -0
- package/dist/reputation.js +78 -0
- package/dist/reputation.js.map +1 -0
- package/dist/swarm.d.ts +78 -0
- package/dist/swarm.d.ts.map +1 -0
- package/dist/swarm.js +182 -0
- package/dist/swarm.js.map +1 -0
- package/dist/validation.d.ts +40 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +73 -0
- package/dist/validation.js.map +1 -0
- package/dist/workspace.d.ts +47 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +93 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# @agent-workspace/utils
|
|
2
|
+
|
|
3
|
+
Shared utilities for the [Agent Workspace Protocol](https://github.com/marcoloco23/awp) packages.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @agent-workspace/utils
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Validation
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { validateSlug, sanitizeSlug, validatePath } from "@agent-workspace/utils";
|
|
17
|
+
|
|
18
|
+
// Validate a slug
|
|
19
|
+
validateSlug("my-artifact"); // true
|
|
20
|
+
validateSlug("Invalid_Slug"); // false
|
|
21
|
+
|
|
22
|
+
// Sanitize and validate (throws on invalid)
|
|
23
|
+
const slug = sanitizeSlug("My-Artifact"); // "my-artifact"
|
|
24
|
+
|
|
25
|
+
// Validate path is within root (prevents traversal)
|
|
26
|
+
const safePath = validatePath("/workspace", "artifacts/doc.md");
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Reputation
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import {
|
|
33
|
+
computeDecayedScore,
|
|
34
|
+
updateDimension,
|
|
35
|
+
computeConfidence,
|
|
36
|
+
} from "@agent-workspace/utils";
|
|
37
|
+
|
|
38
|
+
// Compute decayed score (decays toward 0.5 over time)
|
|
39
|
+
const decayed = computeDecayedScore(dimension, new Date());
|
|
40
|
+
|
|
41
|
+
// Update dimension with new signal using EWMA
|
|
42
|
+
const updated = updateDimension(existingDimension, 0.9);
|
|
43
|
+
|
|
44
|
+
// Compute confidence from sample size
|
|
45
|
+
const confidence = computeConfidence(10); // ~0.5
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Frontmatter
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import {
|
|
52
|
+
parseWorkspaceFile,
|
|
53
|
+
writeWorkspaceFile,
|
|
54
|
+
serializeWorkspaceFile,
|
|
55
|
+
} from "@agent-workspace/utils";
|
|
56
|
+
import type { IdentityFrontmatter } from "@agent-workspace/core";
|
|
57
|
+
|
|
58
|
+
// Parse a workspace file
|
|
59
|
+
const identity = await parseWorkspaceFile<IdentityFrontmatter>("IDENTITY.md");
|
|
60
|
+
console.log(identity.frontmatter.name);
|
|
61
|
+
|
|
62
|
+
// Modify and write back
|
|
63
|
+
identity.frontmatter.lastModified = new Date().toISOString();
|
|
64
|
+
await writeWorkspaceFile(identity);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Part of AWP
|
|
68
|
+
|
|
69
|
+
This package is part of the [Agent Workspace Protocol](https://github.com/marcoloco23/awp) monorepo:
|
|
70
|
+
|
|
71
|
+
| Package | Description |
|
|
72
|
+
|---------|-------------|
|
|
73
|
+
| [@agent-workspace/core](https://www.npmjs.com/package/@agent-workspace/core) | Types, constants, JSON schemas |
|
|
74
|
+
| [@agent-workspace/cli](https://www.npmjs.com/package/@agent-workspace/cli) | CLI tool |
|
|
75
|
+
| [@agent-workspace/mcp-server](https://www.npmjs.com/package/@agent-workspace/mcp-server) | MCP server |
|
|
76
|
+
| **@agent-workspace/utils** | Shared utilities |
|
|
77
|
+
|
|
78
|
+
## License
|
|
79
|
+
|
|
80
|
+
Apache-2.0
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { BaseFrontmatter, WorkspaceFile } from "@agent-workspace/core";
|
|
2
|
+
/**
|
|
3
|
+
* Parse an AWP workspace file (Markdown with YAML frontmatter).
|
|
4
|
+
*
|
|
5
|
+
* @template T - The frontmatter type
|
|
6
|
+
* @param filePath - Path to the file
|
|
7
|
+
* @returns Parsed workspace file
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseWorkspaceFile<T extends BaseFrontmatter>(filePath: string): Promise<WorkspaceFile<T>>;
|
|
10
|
+
/**
|
|
11
|
+
* Serialize a workspace file back to Markdown with YAML frontmatter.
|
|
12
|
+
*
|
|
13
|
+
* @param file - The workspace file to serialize
|
|
14
|
+
* @returns Serialized content string
|
|
15
|
+
*/
|
|
16
|
+
export declare function serializeWorkspaceFile<T extends BaseFrontmatter>(file: WorkspaceFile<T>): string;
|
|
17
|
+
/**
|
|
18
|
+
* Write a workspace file to disk.
|
|
19
|
+
*
|
|
20
|
+
* @param file - The workspace file to write
|
|
21
|
+
*/
|
|
22
|
+
export declare function writeWorkspaceFile<T extends BaseFrontmatter>(file: WorkspaceFile<T>): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Extract the type from frontmatter data.
|
|
25
|
+
*
|
|
26
|
+
* @param data - The frontmatter data
|
|
27
|
+
* @returns The type string or undefined
|
|
28
|
+
*/
|
|
29
|
+
export declare function getFrontmatterType(data: Record<string, unknown>): string | undefined;
|
|
30
|
+
//# sourceMappingURL=frontmatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE5E;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,SAAS,eAAe,EAChE,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAQ3B;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,eAAe,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,CAEhG;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,SAAS,eAAe,EAChE,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,SAAS,CAEpF"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import matter from "gray-matter";
|
|
3
|
+
/**
|
|
4
|
+
* Parse an AWP workspace file (Markdown with YAML frontmatter).
|
|
5
|
+
*
|
|
6
|
+
* @template T - The frontmatter type
|
|
7
|
+
* @param filePath - Path to the file
|
|
8
|
+
* @returns Parsed workspace file
|
|
9
|
+
*/
|
|
10
|
+
export async function parseWorkspaceFile(filePath) {
|
|
11
|
+
const raw = await readFile(filePath, "utf-8");
|
|
12
|
+
const { data, content } = matter(raw);
|
|
13
|
+
return {
|
|
14
|
+
frontmatter: data,
|
|
15
|
+
body: content,
|
|
16
|
+
filePath,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Serialize a workspace file back to Markdown with YAML frontmatter.
|
|
21
|
+
*
|
|
22
|
+
* @param file - The workspace file to serialize
|
|
23
|
+
* @returns Serialized content string
|
|
24
|
+
*/
|
|
25
|
+
export function serializeWorkspaceFile(file) {
|
|
26
|
+
return matter.stringify(file.body, file.frontmatter);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Write a workspace file to disk.
|
|
30
|
+
*
|
|
31
|
+
* @param file - The workspace file to write
|
|
32
|
+
*/
|
|
33
|
+
export async function writeWorkspaceFile(file) {
|
|
34
|
+
const content = serializeWorkspaceFile(file);
|
|
35
|
+
await writeFile(file.filePath, content, "utf-8");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Extract the type from frontmatter data.
|
|
39
|
+
*
|
|
40
|
+
* @param data - The frontmatter data
|
|
41
|
+
* @returns The type string or undefined
|
|
42
|
+
*/
|
|
43
|
+
export function getFrontmatterType(data) {
|
|
44
|
+
return typeof data.type === "string" ? data.type : undefined;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=frontmatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,MAAM,MAAM,aAAa,CAAC;AAGjC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAgB;IAEhB,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtC,OAAO;QACL,WAAW,EAAE,IAAS;QACtB,IAAI,EAAE,OAAO;QACb,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAA4B,IAAsB;IACtF,OAAO,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;AACvD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAsB;IAEtB,MAAM,OAAO,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACnD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAA6B;IAC9D,OAAO,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/D,CAAC"}
|
package/dist/graph.d.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency graph algorithms for task ordering and cycle detection.
|
|
3
|
+
*
|
|
4
|
+
* Implements:
|
|
5
|
+
* - Topological sort (Kahn's algorithm)
|
|
6
|
+
* - Cycle detection (DFS-based)
|
|
7
|
+
* - Critical path analysis
|
|
8
|
+
* - Blocked task identification
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Minimal task node for graph operations.
|
|
12
|
+
*/
|
|
13
|
+
export interface TaskNode {
|
|
14
|
+
/** Task ID in format task:<project>/<slug> */
|
|
15
|
+
id: string;
|
|
16
|
+
/** Task IDs that must complete before this task */
|
|
17
|
+
blockedBy: string[];
|
|
18
|
+
/** Task IDs that are waiting on this task */
|
|
19
|
+
blocks: string[];
|
|
20
|
+
/** Current task status */
|
|
21
|
+
status: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Adjacency list representation of a dependency graph.
|
|
25
|
+
*/
|
|
26
|
+
export interface DependencyGraph {
|
|
27
|
+
/** Map of task ID to task node */
|
|
28
|
+
nodes: Map<string, TaskNode>;
|
|
29
|
+
/** Adjacency list: task ID -> IDs of tasks it depends on (blockedBy) */
|
|
30
|
+
inEdges: Map<string, Set<string>>;
|
|
31
|
+
/** Reverse adjacency: task ID -> IDs of tasks that depend on it (blocks) */
|
|
32
|
+
outEdges: Map<string, Set<string>>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Result of analyzing a task dependency graph.
|
|
36
|
+
*/
|
|
37
|
+
export interface GraphAnalysis {
|
|
38
|
+
/** Topologically sorted task IDs (null if cycle exists) */
|
|
39
|
+
sorted: string[] | null;
|
|
40
|
+
/** Detected cycles (each cycle is an array of task IDs) */
|
|
41
|
+
cycles: string[][];
|
|
42
|
+
/** Critical path (longest dependency chain) */
|
|
43
|
+
criticalPath: string[];
|
|
44
|
+
/** Tasks blocked by incomplete dependencies: task ID -> blocking task IDs */
|
|
45
|
+
blocked: Map<string, string[]>;
|
|
46
|
+
/** True if the graph is a valid DAG (no cycles) */
|
|
47
|
+
isValid: boolean;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Build a dependency graph from a list of task nodes.
|
|
51
|
+
*
|
|
52
|
+
* @param tasks - Array of task nodes
|
|
53
|
+
* @returns Dependency graph with adjacency lists
|
|
54
|
+
*/
|
|
55
|
+
export declare function buildGraph(tasks: TaskNode[]): DependencyGraph;
|
|
56
|
+
/**
|
|
57
|
+
* Topologically sort tasks using Kahn's algorithm.
|
|
58
|
+
* Returns null if a cycle is detected.
|
|
59
|
+
*
|
|
60
|
+
* @param graph - Dependency graph
|
|
61
|
+
* @returns Sorted task IDs in execution order, or null if cycle exists
|
|
62
|
+
*/
|
|
63
|
+
export declare function topologicalSort(graph: DependencyGraph): string[] | null;
|
|
64
|
+
/**
|
|
65
|
+
* Detect all cycles in the dependency graph using DFS.
|
|
66
|
+
*
|
|
67
|
+
* @param graph - Dependency graph
|
|
68
|
+
* @returns Array of cycles, where each cycle is an array of task IDs
|
|
69
|
+
*/
|
|
70
|
+
export declare function detectCycles(graph: DependencyGraph): string[][];
|
|
71
|
+
/**
|
|
72
|
+
* Find the critical path (longest dependency chain) in the graph.
|
|
73
|
+
* Uses dynamic programming on the DAG.
|
|
74
|
+
*
|
|
75
|
+
* @param graph - Dependency graph
|
|
76
|
+
* @returns Array of task IDs forming the critical path
|
|
77
|
+
*/
|
|
78
|
+
export declare function findCriticalPath(graph: DependencyGraph): string[];
|
|
79
|
+
/**
|
|
80
|
+
* Find tasks that are blocked by incomplete dependencies.
|
|
81
|
+
*
|
|
82
|
+
* @param graph - Dependency graph
|
|
83
|
+
* @returns Map of task ID -> array of blocking (incomplete) task IDs
|
|
84
|
+
*/
|
|
85
|
+
export declare function getBlockedTasks(graph: DependencyGraph): Map<string, string[]>;
|
|
86
|
+
/**
|
|
87
|
+
* Perform a complete analysis of the task dependency graph.
|
|
88
|
+
*
|
|
89
|
+
* @param tasks - Array of task nodes
|
|
90
|
+
* @returns Full graph analysis including sort, cycles, critical path, and blocked tasks
|
|
91
|
+
*/
|
|
92
|
+
export declare function analyzeGraph(tasks: TaskNode[]): GraphAnalysis;
|
|
93
|
+
/**
|
|
94
|
+
* Extract the task slug from a full task ID.
|
|
95
|
+
* e.g., "task:q3-launch/research" -> "research"
|
|
96
|
+
*
|
|
97
|
+
* @param taskId - Full task ID
|
|
98
|
+
* @returns Task slug
|
|
99
|
+
*/
|
|
100
|
+
export declare function getTaskSlug(taskId: string): string;
|
|
101
|
+
/**
|
|
102
|
+
* Extract the project slug from a full task ID.
|
|
103
|
+
* e.g., "task:q3-launch/research" -> "q3-launch"
|
|
104
|
+
*
|
|
105
|
+
* @param taskId - Full task ID
|
|
106
|
+
* @returns Project slug
|
|
107
|
+
*/
|
|
108
|
+
export declare function getProjectSlug(taskId: string): string;
|
|
109
|
+
//# sourceMappingURL=graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,8CAA8C;IAC9C,EAAE,EAAE,MAAM,CAAC;IACX,mDAAmD;IACnD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,6CAA6C;IAC7C,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC7B,wEAAwE;IACxE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAClC,4EAA4E;IAC5E,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,2DAA2D;IAC3D,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACxB,2DAA2D;IAC3D,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;IACnB,+CAA+C;IAC/C,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,6EAA6E;IAC7E,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/B,mDAAmD;IACnD,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,eAAe,CAwB7D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,EAAE,GAAG,IAAI,CAuCvE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,EAAE,EAAE,CAmD/D;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,EAAE,CAoDjE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAwB7E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,aAAa,CAc7D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGrD"}
|
package/dist/graph.js
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency graph algorithms for task ordering and cycle detection.
|
|
3
|
+
*
|
|
4
|
+
* Implements:
|
|
5
|
+
* - Topological sort (Kahn's algorithm)
|
|
6
|
+
* - Cycle detection (DFS-based)
|
|
7
|
+
* - Critical path analysis
|
|
8
|
+
* - Blocked task identification
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Build a dependency graph from a list of task nodes.
|
|
12
|
+
*
|
|
13
|
+
* @param tasks - Array of task nodes
|
|
14
|
+
* @returns Dependency graph with adjacency lists
|
|
15
|
+
*/
|
|
16
|
+
export function buildGraph(tasks) {
|
|
17
|
+
const nodes = new Map();
|
|
18
|
+
const inEdges = new Map();
|
|
19
|
+
const outEdges = new Map();
|
|
20
|
+
// Initialize all nodes
|
|
21
|
+
for (const task of tasks) {
|
|
22
|
+
nodes.set(task.id, task);
|
|
23
|
+
inEdges.set(task.id, new Set());
|
|
24
|
+
outEdges.set(task.id, new Set());
|
|
25
|
+
}
|
|
26
|
+
// Build adjacency lists from blockedBy relationships
|
|
27
|
+
for (const task of tasks) {
|
|
28
|
+
for (const dep of task.blockedBy) {
|
|
29
|
+
// Only add edge if both nodes exist in the graph
|
|
30
|
+
if (nodes.has(dep)) {
|
|
31
|
+
inEdges.get(task.id).add(dep);
|
|
32
|
+
outEdges.get(dep).add(task.id);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return { nodes, inEdges, outEdges };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Topologically sort tasks using Kahn's algorithm.
|
|
40
|
+
* Returns null if a cycle is detected.
|
|
41
|
+
*
|
|
42
|
+
* @param graph - Dependency graph
|
|
43
|
+
* @returns Sorted task IDs in execution order, or null if cycle exists
|
|
44
|
+
*/
|
|
45
|
+
export function topologicalSort(graph) {
|
|
46
|
+
const { nodes, inEdges } = graph;
|
|
47
|
+
const result = [];
|
|
48
|
+
// Calculate in-degrees (copy to avoid mutation)
|
|
49
|
+
const inDegree = new Map();
|
|
50
|
+
for (const [id, deps] of inEdges) {
|
|
51
|
+
inDegree.set(id, deps.size);
|
|
52
|
+
}
|
|
53
|
+
// Start with nodes that have no dependencies
|
|
54
|
+
const queue = [];
|
|
55
|
+
for (const [id, degree] of inDegree) {
|
|
56
|
+
if (degree === 0) {
|
|
57
|
+
queue.push(id);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
while (queue.length > 0) {
|
|
61
|
+
const current = queue.shift();
|
|
62
|
+
result.push(current);
|
|
63
|
+
// Reduce in-degree of dependent tasks
|
|
64
|
+
const dependents = graph.outEdges.get(current) || new Set();
|
|
65
|
+
for (const dep of dependents) {
|
|
66
|
+
const newDegree = inDegree.get(dep) - 1;
|
|
67
|
+
inDegree.set(dep, newDegree);
|
|
68
|
+
if (newDegree === 0) {
|
|
69
|
+
queue.push(dep);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// If we didn't process all nodes, there's a cycle
|
|
74
|
+
if (result.length !== nodes.size) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Detect all cycles in the dependency graph using DFS.
|
|
81
|
+
*
|
|
82
|
+
* @param graph - Dependency graph
|
|
83
|
+
* @returns Array of cycles, where each cycle is an array of task IDs
|
|
84
|
+
*/
|
|
85
|
+
export function detectCycles(graph) {
|
|
86
|
+
const { nodes, inEdges } = graph;
|
|
87
|
+
const cycles = [];
|
|
88
|
+
const visited = new Set();
|
|
89
|
+
const recStack = new Set();
|
|
90
|
+
const parent = new Map();
|
|
91
|
+
function dfs(nodeId, path) {
|
|
92
|
+
visited.add(nodeId);
|
|
93
|
+
recStack.add(nodeId);
|
|
94
|
+
path.push(nodeId);
|
|
95
|
+
const deps = inEdges.get(nodeId) || new Set();
|
|
96
|
+
for (const dep of deps) {
|
|
97
|
+
if (!visited.has(dep)) {
|
|
98
|
+
parent.set(dep, nodeId);
|
|
99
|
+
dfs(dep, [...path]);
|
|
100
|
+
}
|
|
101
|
+
else if (recStack.has(dep)) {
|
|
102
|
+
// Found a cycle - extract it
|
|
103
|
+
const cycleStart = path.indexOf(dep);
|
|
104
|
+
if (cycleStart !== -1) {
|
|
105
|
+
const cycle = path.slice(cycleStart);
|
|
106
|
+
cycle.push(dep); // Close the cycle
|
|
107
|
+
cycles.push(cycle);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
recStack.delete(nodeId);
|
|
112
|
+
}
|
|
113
|
+
for (const nodeId of nodes.keys()) {
|
|
114
|
+
if (!visited.has(nodeId)) {
|
|
115
|
+
parent.set(nodeId, null);
|
|
116
|
+
dfs(nodeId, []);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Deduplicate cycles (same cycle can be found from different starting points)
|
|
120
|
+
const uniqueCycles = new Map();
|
|
121
|
+
for (const cycle of cycles) {
|
|
122
|
+
// Normalize: rotate to start with smallest ID
|
|
123
|
+
const minIdx = cycle.indexOf(cycle.slice(0, -1).reduce((a, b) => (a < b ? a : b)));
|
|
124
|
+
const normalized = [...cycle.slice(minIdx, -1), ...cycle.slice(0, minIdx), cycle[minIdx]];
|
|
125
|
+
const key = normalized.join("→");
|
|
126
|
+
if (!uniqueCycles.has(key)) {
|
|
127
|
+
uniqueCycles.set(key, normalized);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return Array.from(uniqueCycles.values());
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Find the critical path (longest dependency chain) in the graph.
|
|
134
|
+
* Uses dynamic programming on the DAG.
|
|
135
|
+
*
|
|
136
|
+
* @param graph - Dependency graph
|
|
137
|
+
* @returns Array of task IDs forming the critical path
|
|
138
|
+
*/
|
|
139
|
+
export function findCriticalPath(graph) {
|
|
140
|
+
const sorted = topologicalSort(graph);
|
|
141
|
+
if (!sorted) {
|
|
142
|
+
// Graph has cycles, can't compute critical path
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
const { inEdges } = graph;
|
|
146
|
+
const dist = new Map();
|
|
147
|
+
const prev = new Map();
|
|
148
|
+
// Initialize distances
|
|
149
|
+
for (const id of sorted) {
|
|
150
|
+
dist.set(id, 0);
|
|
151
|
+
prev.set(id, null);
|
|
152
|
+
}
|
|
153
|
+
// Process in topological order
|
|
154
|
+
for (const nodeId of sorted) {
|
|
155
|
+
const deps = inEdges.get(nodeId) || new Set();
|
|
156
|
+
for (const dep of deps) {
|
|
157
|
+
const newDist = dist.get(dep) + 1;
|
|
158
|
+
if (newDist > dist.get(nodeId)) {
|
|
159
|
+
dist.set(nodeId, newDist);
|
|
160
|
+
prev.set(nodeId, dep);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Find the node with maximum distance (end of critical path)
|
|
165
|
+
let maxDist = 0;
|
|
166
|
+
let endNode = null;
|
|
167
|
+
for (const [id, d] of dist) {
|
|
168
|
+
if (d >= maxDist) {
|
|
169
|
+
maxDist = d;
|
|
170
|
+
endNode = id;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (!endNode) {
|
|
174
|
+
return [];
|
|
175
|
+
}
|
|
176
|
+
// Reconstruct the critical path
|
|
177
|
+
const path = [];
|
|
178
|
+
let current = endNode;
|
|
179
|
+
while (current !== null) {
|
|
180
|
+
path.unshift(current);
|
|
181
|
+
current = prev.get(current) || null;
|
|
182
|
+
}
|
|
183
|
+
return path;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Find tasks that are blocked by incomplete dependencies.
|
|
187
|
+
*
|
|
188
|
+
* @param graph - Dependency graph
|
|
189
|
+
* @returns Map of task ID -> array of blocking (incomplete) task IDs
|
|
190
|
+
*/
|
|
191
|
+
export function getBlockedTasks(graph) {
|
|
192
|
+
const { nodes, inEdges } = graph;
|
|
193
|
+
const blocked = new Map();
|
|
194
|
+
const incompleteTasks = new Set(Array.from(nodes.values())
|
|
195
|
+
.filter((t) => t.status !== "completed" && t.status !== "cancelled")
|
|
196
|
+
.map((t) => t.id));
|
|
197
|
+
for (const [taskId, deps] of inEdges) {
|
|
198
|
+
const task = nodes.get(taskId);
|
|
199
|
+
// Skip already completed/cancelled tasks
|
|
200
|
+
if (task.status === "completed" || task.status === "cancelled") {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
const blockingDeps = Array.from(deps).filter((dep) => incompleteTasks.has(dep));
|
|
204
|
+
if (blockingDeps.length > 0) {
|
|
205
|
+
blocked.set(taskId, blockingDeps);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return blocked;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Perform a complete analysis of the task dependency graph.
|
|
212
|
+
*
|
|
213
|
+
* @param tasks - Array of task nodes
|
|
214
|
+
* @returns Full graph analysis including sort, cycles, critical path, and blocked tasks
|
|
215
|
+
*/
|
|
216
|
+
export function analyzeGraph(tasks) {
|
|
217
|
+
const graph = buildGraph(tasks);
|
|
218
|
+
const sorted = topologicalSort(graph);
|
|
219
|
+
const cycles = detectCycles(graph);
|
|
220
|
+
const criticalPath = findCriticalPath(graph);
|
|
221
|
+
const blocked = getBlockedTasks(graph);
|
|
222
|
+
return {
|
|
223
|
+
sorted,
|
|
224
|
+
cycles,
|
|
225
|
+
criticalPath,
|
|
226
|
+
blocked,
|
|
227
|
+
isValid: cycles.length === 0,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Extract the task slug from a full task ID.
|
|
232
|
+
* e.g., "task:q3-launch/research" -> "research"
|
|
233
|
+
*
|
|
234
|
+
* @param taskId - Full task ID
|
|
235
|
+
* @returns Task slug
|
|
236
|
+
*/
|
|
237
|
+
export function getTaskSlug(taskId) {
|
|
238
|
+
const parts = taskId.split("/");
|
|
239
|
+
return parts[parts.length - 1];
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Extract the project slug from a full task ID.
|
|
243
|
+
* e.g., "task:q3-launch/research" -> "q3-launch"
|
|
244
|
+
*
|
|
245
|
+
* @param taskId - Full task ID
|
|
246
|
+
* @returns Project slug
|
|
247
|
+
*/
|
|
248
|
+
export function getProjectSlug(taskId) {
|
|
249
|
+
const match = taskId.match(/^task:([^/]+)/);
|
|
250
|
+
return match ? match[1] : "";
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.js","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @agent-workspace/utils
|
|
3
|
+
*
|
|
4
|
+
* Shared utilities for AWP packages including validation,
|
|
5
|
+
* reputation calculations, frontmatter parsing, and workspace helpers.
|
|
6
|
+
*/
|
|
7
|
+
export { validateSlug, sanitizeSlug, validatePath, isValidDate, isValidTimestamp, } from "./validation.js";
|
|
8
|
+
export { computeConfidence, computeDecayedScore, updateDimension, computeWeightedScore, } from "./reputation.js";
|
|
9
|
+
export { parseWorkspaceFile, serializeWorkspaceFile, writeWorkspaceFile, getFrontmatterType, } from "./frontmatter.js";
|
|
10
|
+
export { findWorkspaceRoot, loadManifest, fileExists, getAgentDid, safeReadFile, getWorkspaceRoot, } from "./workspace.js";
|
|
11
|
+
export { type TaskNode, type DependencyGraph, type GraphAnalysis, buildGraph, topologicalSort, detectCycles, findCriticalPath, getBlockedTasks, analyzeGraph, getTaskSlug, getProjectSlug, } from "./graph.js";
|
|
12
|
+
export { type RecruitmentCandidate, type RecruitmentResult, findCandidatesForRole, autoRecruitSwarm, isSwarmFullyStaffed, getSwarmStaffingSummary, } from "./swarm.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,WAAW,EACX,YAAY,EACZ,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,UAAU,EACV,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,WAAW,EACX,cAAc,GACf,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @agent-workspace/utils
|
|
3
|
+
*
|
|
4
|
+
* Shared utilities for AWP packages including validation,
|
|
5
|
+
* reputation calculations, frontmatter parsing, and workspace helpers.
|
|
6
|
+
*/
|
|
7
|
+
// Validation utilities
|
|
8
|
+
export { validateSlug, sanitizeSlug, validatePath, isValidDate, isValidTimestamp, } from "./validation.js";
|
|
9
|
+
// Reputation utilities
|
|
10
|
+
export { computeConfidence, computeDecayedScore, updateDimension, computeWeightedScore, } from "./reputation.js";
|
|
11
|
+
// Frontmatter utilities
|
|
12
|
+
export { parseWorkspaceFile, serializeWorkspaceFile, writeWorkspaceFile, getFrontmatterType, } from "./frontmatter.js";
|
|
13
|
+
// Workspace utilities
|
|
14
|
+
export { findWorkspaceRoot, loadManifest, fileExists, getAgentDid, safeReadFile, getWorkspaceRoot, } from "./workspace.js";
|
|
15
|
+
// Graph utilities (dependency analysis)
|
|
16
|
+
export { buildGraph, topologicalSort, detectCycles, findCriticalPath, getBlockedTasks, analyzeGraph, getTaskSlug, getProjectSlug, } from "./graph.js";
|
|
17
|
+
// Swarm utilities (recruitment)
|
|
18
|
+
export { findCandidatesForRole, autoRecruitSwarm, isSwarmFullyStaffed, getSwarmStaffingSummary, } from "./swarm.js";
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,uBAAuB;AACvB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAEzB,uBAAuB;AACvB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAEzB,wBAAwB;AACxB,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAE1B,sBAAsB;AACtB,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,WAAW,EACX,YAAY,EACZ,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,wCAAwC;AACxC,OAAO,EAIL,UAAU,EACV,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,WAAW,EACX,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,gCAAgC;AAChC,OAAO,EAGL,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ReputationDimension } from "@agent-workspace/core";
|
|
2
|
+
/**
|
|
3
|
+
* Compute confidence from sample size.
|
|
4
|
+
* Formula: confidence = 1 - 1/(1 + sampleSize * 0.1)
|
|
5
|
+
*
|
|
6
|
+
* @param sampleSize - Number of samples
|
|
7
|
+
* @returns Confidence value (0.0 to ~1.0)
|
|
8
|
+
*/
|
|
9
|
+
export declare function computeConfidence(sampleSize: number): number;
|
|
10
|
+
/**
|
|
11
|
+
* Apply time-based decay to a reputation score.
|
|
12
|
+
* Scores decay toward REPUTATION_BASELINE (0.5) over time.
|
|
13
|
+
*
|
|
14
|
+
* @param dim - The reputation dimension to decay
|
|
15
|
+
* @param now - Current date (defaults to now)
|
|
16
|
+
* @param decayRate - Monthly decay rate (defaults to REPUTATION_DECAY_RATE)
|
|
17
|
+
* @returns The decayed score
|
|
18
|
+
*/
|
|
19
|
+
export declare function computeDecayedScore(dim: ReputationDimension, now?: Date, decayRate?: number): number;
|
|
20
|
+
/**
|
|
21
|
+
* Update a reputation dimension with a new signal using EWMA.
|
|
22
|
+
*
|
|
23
|
+
* @param existing - Existing dimension (undefined for first signal)
|
|
24
|
+
* @param signalScore - The new signal score (0.0 to 1.0)
|
|
25
|
+
* @param now - Current date (defaults to now)
|
|
26
|
+
* @param alpha - EWMA learning rate (defaults to REPUTATION_EWMA_ALPHA)
|
|
27
|
+
* @returns Updated reputation dimension
|
|
28
|
+
*/
|
|
29
|
+
export declare function updateDimension(existing: ReputationDimension | undefined, signalScore: number, now?: Date, alpha?: number): ReputationDimension;
|
|
30
|
+
/**
|
|
31
|
+
* Compute a weighted average of multiple dimension scores.
|
|
32
|
+
*
|
|
33
|
+
* @param scores - Array of [score, weight] tuples
|
|
34
|
+
* @returns Weighted average score
|
|
35
|
+
*/
|
|
36
|
+
export declare function computeWeightedScore(scores: Array<[number, number]>): number;
|
|
37
|
+
//# sourceMappingURL=reputation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reputation.d.ts","sourceRoot":"","sources":["../src/reputation.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,mBAAmB,EACzB,MAAM,uBAAuB,CAAC;AAE/B;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,mBAAmB,EACxB,GAAG,GAAE,IAAiB,EACtB,SAAS,GAAE,MAA8B,GACxC,MAAM,CAYR;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,mBAAmB,GAAG,SAAS,EACzC,WAAW,EAAE,MAAM,EACnB,GAAG,GAAE,IAAiB,EACtB,KAAK,GAAE,MAA8B,GACpC,mBAAmB,CAuBrB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAY5E"}
|