yuangs 3.21.0 → 3.22.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.
Files changed (66) hide show
  1. package/dist/agent/AgentRuntime.js +32 -7
  2. package/dist/agent/AgentRuntime.js.map +1 -1
  3. package/dist/agent/context.d.ts +5 -0
  4. package/dist/agent/context.js +24 -4
  5. package/dist/agent/context.js.map +1 -1
  6. package/dist/agent/governance.js +10 -0
  7. package/dist/agent/governance.js.map +1 -1
  8. package/dist/agent/llm.js +6 -2
  9. package/dist/agent/llm.js.map +1 -1
  10. package/dist/agent/prompt.js +6 -6
  11. package/dist/agent/prompt.js.map +1 -1
  12. package/dist/cli.js +34 -4
  13. package/dist/cli.js.map +1 -1
  14. package/dist/commands/handleAIChat.js +31 -1
  15. package/dist/commands/handleAIChat.js.map +1 -1
  16. package/dist/commands/preferencesCommands.d.ts +2 -0
  17. package/dist/commands/preferencesCommands.js +232 -0
  18. package/dist/commands/preferencesCommands.js.map +1 -0
  19. package/package.json +1 -1
  20. package/dist/Capabilities.js +0 -39
  21. package/dist/Governance.d.ts +0 -9
  22. package/dist/Governance.js +0 -25
  23. package/dist/Kernel.d.ts +0 -13
  24. package/dist/Kernel.js +0 -53
  25. package/dist/agent/AgentPipeline.d.ts +0 -5
  26. package/dist/agent/AgentPipeline.js +0 -105
  27. package/dist/agent/fsm.d.ts +0 -23
  28. package/dist/agent/fsm.js +0 -95
  29. package/dist/agent/intent.d.ts +0 -2
  30. package/dist/agent/intent.js +0 -28
  31. package/dist/agent/interpret.d.ts +0 -3
  32. package/dist/agent/interpret.js +0 -39
  33. package/dist/agent/loop.d.ts +0 -21
  34. package/dist/agent/loop.js +0 -214
  35. package/dist/agent/plan.d.ts +0 -13
  36. package/dist/agent/plan.js +0 -3
  37. package/dist/agent/planExecutor.d.ts +0 -10
  38. package/dist/agent/planExecutor.js +0 -74
  39. package/dist/agent/record.d.ts +0 -14
  40. package/dist/agent/record.js +0 -20
  41. package/dist/agent/replay.d.ts +0 -2
  42. package/dist/agent/replay.js +0 -25
  43. package/dist/commands/chatHistoryStorage.d.ts +0 -4
  44. package/dist/commands/chatHistoryStorage.js +0 -54
  45. package/dist/governance/GovernanceEngine.d.ts +0 -20
  46. package/dist/governance/GovernanceEngine.js +0 -95
  47. package/dist/governance/GovernedAction.d.ts +0 -107
  48. package/dist/governance/GovernedAction.js +0 -9
  49. package/dist/governance/actions/CodeChangeAction.d.ts +0 -28
  50. package/dist/governance/actions/CodeChangeAction.js +0 -139
  51. package/dist/governance/capability/token.d.ts +0 -45
  52. package/dist/governance/capability/token.js +0 -103
  53. package/dist/governance/commands/diffEdit.d.ts +0 -2
  54. package/dist/governance/commands/diffEdit.js +0 -245
  55. package/dist/governance/execution/sandbox.d.ts +0 -12
  56. package/dist/governance/execution/sandbox.js +0 -76
  57. package/dist/governance/fsm/stateMachine.d.ts +0 -40
  58. package/dist/governance/fsm/stateMachine.js +0 -93
  59. package/dist/governance/index.d.ts +0 -9
  60. package/dist/governance/index.js +0 -26
  61. package/dist/governance/review/diffParser.d.ts +0 -12
  62. package/dist/governance/review/diffParser.js +0 -61
  63. package/dist/governance/review/render.d.ts +0 -5
  64. package/dist/governance/review/render.js +0 -58
  65. package/dist/governance/storage/store.d.ts +0 -16
  66. package/dist/governance/storage/store.js +0 -110
@@ -1,2 +0,0 @@
1
- import { ExecutionRecord } from './record';
2
- export declare function replay(record: ExecutionRecord): Promise<import("./plan").AgentPlan>;
@@ -1,25 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.replay = replay;
4
- const llm_1 = require("./llm");
5
- const interpret_1 = require("./interpret");
6
- async function replay(record) {
7
- console.log(`\nReplaying execution: ${record.id}`);
8
- console.log(`Original timestamp: ${new Date(record.timestamp).toISOString()}`);
9
- console.log(`Mode: ${record.mode}\n`);
10
- const result = await (0, llm_1.runLLM)({
11
- prompt: record.prompt,
12
- model: record.model,
13
- stream: record.mode === 'chat',
14
- onChunk: record.mode === 'chat'
15
- ? (s) => process.stdout.write(s)
16
- : undefined,
17
- });
18
- // Create a minimal intent for interpretation
19
- const intent = {
20
- type: record.mode === 'chat' ? 'chat' : 'shell',
21
- capabilities: {},
22
- };
23
- return (0, interpret_1.interpretResultToPlan)(result, intent, record.mode);
24
- }
25
- //# sourceMappingURL=replay.js.map
@@ -1,4 +0,0 @@
1
- import { AIRequestMessage } from '../core/validation';
2
- export declare function loadChatHistory(): Promise<AIRequestMessage[]>;
3
- export declare function saveChatHistory(history: AIRequestMessage[]): Promise<void>;
4
- export declare function clearChatHistory(): Promise<void>;
@@ -1,54 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.loadChatHistory = loadChatHistory;
7
- exports.saveChatHistory = saveChatHistory;
8
- exports.clearChatHistory = clearChatHistory;
9
- const fs_1 = __importDefault(require("fs"));
10
- const util_1 = require("util");
11
- const path_1 = __importDefault(require("path"));
12
- const os_1 = __importDefault(require("os"));
13
- const CHAT_HISTORY_DIR = path_1.default.resolve(os_1.default.homedir(), '.yuangs_chat_history');
14
- const CHAT_HISTORY_FILE = path_1.default.join(CHAT_HISTORY_DIR, 'chat_history.json');
15
- const readFileAsync = (0, util_1.promisify)(fs_1.default.readFile);
16
- const writeFileAsync = (0, util_1.promisify)(fs_1.default.writeFile);
17
- const mkdirAsync = (0, util_1.promisify)(fs_1.default.mkdir);
18
- const rmAsync = (0, util_1.promisify)(fs_1.default.rm);
19
- async function loadChatHistory() {
20
- if (fs_1.default.existsSync(CHAT_HISTORY_FILE)) {
21
- try {
22
- const raw = await readFileAsync(CHAT_HISTORY_FILE, 'utf-8');
23
- const data = JSON.parse(raw);
24
- // 验证数据结构
25
- if (Array.isArray(data) && data.every(msg => typeof msg === 'object' &&
26
- ['user', 'assistant', 'system'].includes(msg.role) &&
27
- typeof msg.content === 'string')) {
28
- return data;
29
- }
30
- }
31
- catch (e) {
32
- console.warn('警告: 加载聊天历史记录失败,使用空历史记录');
33
- }
34
- }
35
- return [];
36
- }
37
- async function saveChatHistory(history) {
38
- try {
39
- await mkdirAsync(CHAT_HISTORY_DIR, { recursive: true });
40
- await writeFileAsync(CHAT_HISTORY_FILE, JSON.stringify(history, null, 2));
41
- }
42
- catch (e) {
43
- console.error('错误: 保存聊天历史记录失败:', e);
44
- }
45
- }
46
- async function clearChatHistory() {
47
- try {
48
- await rmAsync(CHAT_HISTORY_FILE, { force: true });
49
- }
50
- catch (e) {
51
- console.error('错误: 清除聊天历史记录失败:', e);
52
- }
53
- }
54
- //# sourceMappingURL=chatHistoryStorage.js.map
@@ -1,20 +0,0 @@
1
- import { GovernedAction, ExecutionContext, ApprovalSource } from "./GovernedAction";
2
- /**
3
- * Governance engine - single point of control for all governed actions
4
- * Enforces "No Diff Without Review. No Execution Without Approval."
5
- */
6
- export declare class GovernanceEngine {
7
- private actions;
8
- private revokedActions;
9
- register(action: GovernedAction): void;
10
- getAction(id: string): GovernedAction | undefined;
11
- listActions(): GovernedAction[];
12
- requestApproval(id: string): void;
13
- approve(id: string, by: ApprovalSource): void;
14
- reject(id: string, reason: string): void;
15
- execute(id: string, ctx: ExecutionContext): Promise<void>;
16
- observe(id: string): Promise<void>;
17
- verify(id: string, obs: any): boolean;
18
- revoke(id: string): void;
19
- has(id: string): boolean;
20
- }
@@ -1,95 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GovernanceEngine = void 0;
4
- /**
5
- * Governance engine - single point of control for all governed actions
6
- * Enforces "No Diff Without Review. No Execution Without Approval."
7
- */
8
- class GovernanceEngine {
9
- actions = new Map();
10
- revokedActions = new Set();
11
- register(action) {
12
- if (this.revokedActions.has(action.id)) {
13
- throw new Error(`Governance violation: action ${action.id} was revoked`);
14
- }
15
- this.actions.set(action.id, action);
16
- }
17
- getAction(id) {
18
- return this.actions.get(id);
19
- }
20
- listActions() {
21
- return Array.from(this.actions.values());
22
- }
23
- requestApproval(id) {
24
- const action = this.actions.get(id);
25
- if (!action) {
26
- throw new Error(`Action not found: ${id}`);
27
- }
28
- action.propose();
29
- console.log(`[PROPOSED] ${action.kind}:${id}`);
30
- console.log(`Rationale: ${action.rationale}`);
31
- }
32
- approve(id, by) {
33
- const action = this.actions.get(id);
34
- if (!action) {
35
- throw new Error(`Action not found: ${id}`);
36
- }
37
- if (by !== "human") {
38
- throw new Error(`Governance violation: only human can approve`);
39
- }
40
- action.approve(by);
41
- console.log(`[APPROVED] ${action.kind}:${id} by ${by}`);
42
- }
43
- reject(id, reason) {
44
- const action = this.actions.get(id);
45
- if (!action) {
46
- throw new Error(`Action not found: ${id}`);
47
- }
48
- action.reject(reason);
49
- console.log(`[REJECTED] ${action.kind}:${id}`);
50
- console.log(`Reason: ${reason}`);
51
- }
52
- async execute(id, ctx) {
53
- const action = this.actions.get(id);
54
- if (!action) {
55
- throw new Error(`Action not found: ${id}`);
56
- }
57
- if (action.state !== "APPROVED") {
58
- throw new Error(`Governance violation: execute() called on ${action.kind}:${id} in state ${action.state}, must be APPROVED`);
59
- }
60
- const result = await action.execute(ctx);
61
- if (!result.ok) {
62
- throw new Error(`Execution failed: ${result.error || "unknown error"}`);
63
- }
64
- console.log(`[EXECUTED] ${action.kind}:${id}`);
65
- }
66
- async observe(id) {
67
- const action = this.actions.get(id);
68
- if (!action) {
69
- throw new Error(`Action not found: ${id}`);
70
- }
71
- const obs = await action.observe();
72
- console.log(`[OBSERVED] ${action.kind}:${id}`);
73
- console.log(`Files changed: ${obs.changedFiles.length}`);
74
- }
75
- verify(id, obs) {
76
- const action = this.actions.get(id);
77
- if (!action) {
78
- throw new Error(`Action not found: ${id}`);
79
- }
80
- const verified = action.verify(obs);
81
- if (verified) {
82
- console.log(`[VERIFIED] ${action.kind}:${id}`);
83
- }
84
- return verified;
85
- }
86
- revoke(id) {
87
- this.actions.delete(id);
88
- this.revokedActions.add(id);
89
- }
90
- has(id) {
91
- return this.actions.has(id) && !this.revokedActions.has(id);
92
- }
93
- }
94
- exports.GovernanceEngine = GovernanceEngine;
95
- //# sourceMappingURL=GovernanceEngine.js.map
@@ -1,107 +0,0 @@
1
- /**
2
- * Core Governance Types and Interfaces
3
- *
4
- * This module defines the foundational types for the Code Change Governance System.
5
- * All actions must implement GovernedAction and follow strict state transitions.
6
- */
7
- /**
8
- * Valid governance states for any action
9
- * No action can skip states or bypass approval
10
- */
11
- export type GovernanceState = "DRAFT" | "PROPOSED" | "APPROVED" | "EXECUTED" | "OBSERVED" | "VERIFIED" | "REJECTED";
12
- /**
13
- * Approval can only come from humans - no auto-approval
14
- */
15
- export type ApprovalSource = "human";
16
- /**
17
- * Provenance tracking for reproducibility and audit
18
- */
19
- export interface ActionProvenance {
20
- /** The agent that created this action */
21
- agentId: string;
22
- /** Hash of the plan that generated this action */
23
- planHash: string;
24
- /** Parent action if this is a fix/repair attempt */
25
- parentAction?: string;
26
- /** When this action was created */
27
- createdAt: number;
28
- }
29
- /**
30
- * Execution context for running actions
31
- */
32
- export interface ExecutionContext {
33
- executor: ActionExecutor;
34
- snapshot?: string;
35
- }
36
- /**
37
- * Result from executing an action
38
- */
39
- export interface ExecutionResult {
40
- ok: boolean;
41
- error?: string;
42
- executedAt?: number;
43
- snapshotAfter?: string;
44
- }
45
- /**
46
- * Observation data after execution
47
- */
48
- export interface Observation {
49
- gitDiff: string;
50
- changedFiles: string[];
51
- executionTime: number;
52
- }
53
- /**
54
- * Action executor interface (filesystem operations)
55
- * This is the ONLY place where filesystem changes can happen
56
- */
57
- export interface ActionExecutor {
58
- applyDiff(diff: string): Promise<void>;
59
- readFile(path: string): Promise<string>;
60
- writeFile(path: string, content: string): Promise<void>;
61
- deleteFile(path: string): Promise<void>;
62
- }
63
- /**
64
- * Core interface that ALL governed actions must implement
65
- * This enforces the constitutional constraints
66
- */
67
- export interface GovernedAction<Payload = unknown> {
68
- /** Unique identifier for this action */
69
- readonly id: string;
70
- /** Type/kind of action (code_change, run_command, etc.) */
71
- readonly kind: string;
72
- /** The actual payload that will be executed */
73
- readonly payload: Payload;
74
- /** Current state of this action */
75
- state: GovernanceState;
76
- /** Why this action is being proposed (must be human-readable) */
77
- readonly rationale: string;
78
- /** Who created this action and when */
79
- readonly provenance: ActionProvenance;
80
- /** When was the state last updated */
81
- updatedAt: number;
82
- /** Transition from DRAFT to PROPOSED */
83
- propose(): void;
84
- /** Transition from PROPOSED to APPROVED (only human can approve) */
85
- approve(by: ApprovalSource): void;
86
- /** Transition from any state to REJECTED */
87
- reject(reason: string): void;
88
- /** Execute the action (only possible if APPROVED) */
89
- execute(ctx: ExecutionContext): Promise<ExecutionResult>;
90
- /** Observe the results of execution (only possible if EXECUTED) */
91
- observe(): Promise<Observation>;
92
- /** Verify the observation (only possible if OBSERVED) */
93
- verify(obs: Observation): boolean;
94
- /** Get a summary of this action for display */
95
- summarize(): ActionSummary;
96
- }
97
- /**
98
- * Human-readable summary of an action
99
- */
100
- export interface ActionSummary {
101
- id: string;
102
- kind: string;
103
- state: GovernanceState;
104
- rationale: string;
105
- filesAffected?: string[];
106
- changeSize?: number;
107
- }
@@ -1,9 +0,0 @@
1
- "use strict";
2
- /**
3
- * Core Governance Types and Interfaces
4
- *
5
- * This module defines the foundational types for the Code Change Governance System.
6
- * All actions must implement GovernedAction and follow strict state transitions.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- //# sourceMappingURL=GovernedAction.js.map
@@ -1,28 +0,0 @@
1
- import { GovernedAction, GovernanceState, ExecutionContext, ExecutionResult, Observation, ActionSummary, ApprovalSource, ActionProvenance } from "../GovernedAction";
2
- /**
3
- * Payload for code change actions
4
- * Contains unified diff and affected files
5
- */
6
- export interface CodeChangePayload {
7
- files: string[];
8
- diff: string;
9
- }
10
- export declare class CodeChangeAction implements GovernedAction<CodeChangePayload> {
11
- readonly id: string;
12
- readonly payload: CodeChangePayload;
13
- readonly rationale: string;
14
- readonly provenance: ActionProvenance;
15
- readonly kind = "code_change";
16
- state: GovernanceState;
17
- updatedAt: number;
18
- constructor(id: string, payload: CodeChangePayload, rationale: string, provenance: ActionProvenance);
19
- propose(): void;
20
- approve(by: ApprovalSource): void;
21
- reject(reason: string): void;
22
- execute(ctx: ExecutionContext): Promise<ExecutionResult>;
23
- observe(): Promise<Observation>;
24
- verify(obs: Observation): boolean;
25
- summarize(): ActionSummary;
26
- private calculateChangeSize;
27
- static create(payload: CodeChangePayload, rationale: string, agentId: string, planHash: string, parentAction?: string): CodeChangeAction;
28
- }
@@ -1,139 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.CodeChangeAction = void 0;
7
- const crypto_1 = __importDefault(require("crypto"));
8
- class CodeChangeAction {
9
- id;
10
- payload;
11
- rationale;
12
- provenance;
13
- kind = "code_change";
14
- state = "DRAFT";
15
- updatedAt = Date.now();
16
- constructor(id, payload, rationale, provenance) {
17
- this.id = id;
18
- this.payload = payload;
19
- this.rationale = rationale;
20
- this.provenance = provenance;
21
- this.updatedAt = provenance.createdAt;
22
- }
23
- propose() {
24
- if (this.state !== "DRAFT") {
25
- throw new Error(`Governance violation: propose() called from ${this.state}, must be DRAFT`);
26
- }
27
- this.state = "PROPOSED";
28
- this.updatedAt = Date.now();
29
- }
30
- approve(by) {
31
- if (this.state !== "PROPOSED") {
32
- throw new Error(`Governance violation: approve() called from ${this.state}, must be PROPOSED`);
33
- }
34
- if (by !== "human") {
35
- throw new Error(`Governance violation: only human can approve, got ${by}`);
36
- }
37
- this.state = "APPROVED";
38
- this.updatedAt = Date.now();
39
- }
40
- reject(reason) {
41
- if (this.state === "REJECTED") {
42
- throw new Error(`Governance violation: reject() called from ${this.state}, already rejected`);
43
- }
44
- this.state = "REJECTED";
45
- this.updatedAt = Date.now();
46
- }
47
- async execute(ctx) {
48
- if (this.state !== "APPROVED") {
49
- throw new Error(`Governance violation: execute() called from ${this.state}, must be APPROVED`);
50
- }
51
- const startTime = Date.now();
52
- try {
53
- await ctx.executor.applyDiff(this.payload.diff);
54
- this.state = "EXECUTED";
55
- this.updatedAt = Date.now();
56
- return {
57
- ok: true,
58
- executedAt: Date.now(),
59
- snapshotAfter: ctx.snapshot,
60
- };
61
- }
62
- catch (error) {
63
- this.state = "REJECTED";
64
- this.updatedAt = Date.now();
65
- return {
66
- ok: false,
67
- error: error instanceof Error ? error.message : String(error),
68
- };
69
- }
70
- }
71
- async observe() {
72
- if (this.state !== "EXECUTED") {
73
- throw new Error(`Governance violation: observe() called from ${this.state}, must be EXECUTED`);
74
- }
75
- const { execSync } = require("child_process");
76
- const changedFiles = execSync("git diff --name-only", {
77
- encoding: "utf-8",
78
- })
79
- .trim()
80
- .split("\n")
81
- .filter((f) => f);
82
- const gitDiff = execSync("git diff", { encoding: "utf-8" });
83
- this.state = "OBSERVED";
84
- this.updatedAt = Date.now();
85
- return {
86
- gitDiff,
87
- changedFiles,
88
- executionTime: Date.now(),
89
- };
90
- }
91
- verify(obs) {
92
- if (this.state !== "OBSERVED") {
93
- throw new Error(`Governance violation: verify() called from ${this.state}, must be OBSERVED`);
94
- }
95
- const changedFiles = new Set(obs.changedFiles);
96
- const declaredFiles = new Set(this.payload.files);
97
- const extraFiles = obs.changedFiles.filter((f) => !declaredFiles.has(f));
98
- if (extraFiles.length > 0) {
99
- throw new Error(`Governance violation: execution modified undeclared files: ${extraFiles.join(", ")}`);
100
- }
101
- this.state = "VERIFIED";
102
- this.updatedAt = Date.now();
103
- return true;
104
- }
105
- summarize() {
106
- const changeSize = this.calculateChangeSize();
107
- return {
108
- id: this.id,
109
- kind: this.kind,
110
- state: this.state,
111
- rationale: this.rationale,
112
- filesAffected: this.payload.files,
113
- changeSize,
114
- };
115
- }
116
- calculateChangeSize() {
117
- let additions = 0;
118
- let deletions = 0;
119
- for (const line of this.payload.diff.split("\n")) {
120
- if (line.startsWith("+") && !line.startsWith("+++"))
121
- additions++;
122
- if (line.startsWith("-") && !line.startsWith("---"))
123
- deletions++;
124
- }
125
- return additions + deletions;
126
- }
127
- static create(payload, rationale, agentId, planHash, parentAction) {
128
- const id = crypto_1.default.randomUUID();
129
- const provenance = {
130
- agentId,
131
- planHash,
132
- parentAction,
133
- createdAt: Date.now(),
134
- };
135
- return new CodeChangeAction(id, payload, rationale, provenance);
136
- }
137
- }
138
- exports.CodeChangeAction = CodeChangeAction;
139
- //# sourceMappingURL=CodeChangeAction.js.map
@@ -1,45 +0,0 @@
1
- export type Right = {
2
- type: "APPLY_DIFF";
3
- } | {
4
- type: "READ_FILE";
5
- path: string;
6
- } | {
7
- type: "EXECUTE_ACTION";
8
- actionId: string;
9
- };
10
- export type Scope = {
11
- type: "ACTION";
12
- id: string;
13
- } | {
14
- type: "PATH_PREFIX";
15
- prefix: string;
16
- } | {
17
- type: "REPO";
18
- };
19
- export interface Capability {
20
- id: string;
21
- subject: string;
22
- rights: Right[];
23
- scope: Scope;
24
- issuedAt: number;
25
- expiresAt: number;
26
- maxUses: number;
27
- used: number;
28
- signature: string;
29
- }
30
- export declare function sign(data: string): string;
31
- export declare function verify(cap: Capability): boolean;
32
- export declare function issue(input: {
33
- subject: string;
34
- rights: Right[];
35
- scope: Scope;
36
- ttlMs: number;
37
- maxUses?: number;
38
- }): Capability;
39
- export declare function checkCapability(cap: Capability, want: Right, context: {
40
- actionId?: string;
41
- path?: string;
42
- }): void;
43
- export declare function attenuate(cap: Capability, limits: Partial<Pick<Capability, "expiresAt" | "maxUses">>): Capability;
44
- export declare function revoke(capId: string): void;
45
- export declare function checkRevoked(cap: Capability): void;
@@ -1,103 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.sign = sign;
7
- exports.verify = verify;
8
- exports.issue = issue;
9
- exports.checkCapability = checkCapability;
10
- exports.attenuate = attenuate;
11
- exports.revoke = revoke;
12
- exports.checkRevoked = checkRevoked;
13
- const crypto_1 = __importDefault(require("crypto"));
14
- const SECRET = process.env.CAP_SECRET || "default-secret-change-in-production";
15
- function sign(data) {
16
- return crypto_1.default
17
- .createHmac("sha256", SECRET)
18
- .update(data)
19
- .digest("hex");
20
- }
21
- function verify(cap) {
22
- const { signature, ...rest } = cap;
23
- const payload = JSON.stringify(rest);
24
- const computed = sign(payload);
25
- return computed === signature;
26
- }
27
- function issue(input) {
28
- const base = {
29
- id: crypto_1.default.randomUUID(),
30
- subject: input.subject,
31
- rights: input.rights,
32
- scope: input.scope,
33
- issuedAt: Date.now(),
34
- expiresAt: Date.now() + input.ttlMs,
35
- maxUses: input.maxUses ?? 1,
36
- used: 0,
37
- };
38
- const payload = JSON.stringify(base);
39
- return {
40
- ...base,
41
- signature: sign(payload),
42
- };
43
- }
44
- function checkCapability(cap, want, context) {
45
- if (!verify(cap)) {
46
- throw new Error("Invalid capability: signature verification failed");
47
- }
48
- if (Date.now() > cap.expiresAt) {
49
- throw new Error("Capability expired");
50
- }
51
- if (cap.used >= cap.maxUses) {
52
- throw new Error("Capability exhausted (max uses reached)");
53
- }
54
- const rightMatch = cap.rights.some((r) => JSON.stringify(r) === JSON.stringify(want));
55
- if (!rightMatch) {
56
- throw new Error(`Capability does not grant right: ${JSON.stringify(want)}`);
57
- }
58
- if (cap.scope.type === "ACTION" && context.actionId !== cap.scope.id) {
59
- throw new Error(`Scope violation: capability scoped to action ${cap.scope.id}, used on ${context.actionId}`);
60
- }
61
- if (cap.scope.type === "PATH_PREFIX" &&
62
- context.path &&
63
- !context.path.startsWith(cap.scope.prefix)) {
64
- throw new Error(`Scope violation: capability scoped to ${cap.scope.prefix}, used on ${context.path}`);
65
- }
66
- cap.used++;
67
- }
68
- function attenuate(cap, limits) {
69
- if (!verify(cap)) {
70
- throw new Error("Cannot attenuate invalid capability");
71
- }
72
- const reduced = {
73
- ...cap,
74
- expiresAt: Math.min(cap.expiresAt, limits.expiresAt ?? cap.expiresAt),
75
- maxUses: Math.min(cap.maxUses, limits.maxUses ?? cap.maxUses),
76
- used: 0,
77
- signature: "",
78
- };
79
- const payload = JSON.stringify({
80
- id: reduced.id,
81
- subject: reduced.subject,
82
- rights: reduced.rights,
83
- scope: reduced.scope,
84
- issuedAt: reduced.issuedAt,
85
- expiresAt: reduced.expiresAt,
86
- maxUses: reduced.maxUses,
87
- used: 0,
88
- });
89
- return {
90
- ...reduced,
91
- signature: sign(payload),
92
- };
93
- }
94
- const revokedCaps = new Set();
95
- function revoke(capId) {
96
- revokedCaps.add(capId);
97
- }
98
- function checkRevoked(cap) {
99
- if (revokedCaps.has(cap.id)) {
100
- throw new Error(`Capability ${cap.id} has been revoked`);
101
- }
102
- }
103
- //# sourceMappingURL=token.js.map
@@ -1,2 +0,0 @@
1
- import { Command } from "commander";
2
- export declare function createDiffEditCommand(): Command;