@granular-software/sdk 0.4.36 → 0.4.37

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 CHANGED
@@ -70,7 +70,7 @@ const env = await granular.openEnvironment({
70
70
  ontology: "my-ontology",
71
71
  tag: "dev",
72
72
  userId: "user_123",
73
- permissions: ["agent"],
73
+ permissions: ["allow-all"],
74
74
  name: "Jane Doe", // optional
75
75
  email: "jane@example.com", // optional
76
76
  });
@@ -268,7 +268,7 @@ const env = await granular.openEnvironment({
268
268
  ontology: "library-app",
269
269
  tag: "dev",
270
270
  userId: "user_123",
271
- permissions: ["agent"],
271
+ permissions: ["allow-all"],
272
272
  });
273
273
 
274
274
  const [tolkien, lotr] = await env.recordObjects(
@@ -380,6 +380,86 @@ await granular.ontology(env.sandboxId).effects.registerMany([
380
380
  ]);
381
381
  ```
382
382
 
383
+ ## Permission Profiles and Policies
384
+
385
+ Policies are versioned with the ontology. Author role profiles as JSON files under `permissions/`, then run `granular build` or `granular deploy`; the CLI validates and syncs those files before the build.
386
+
387
+ Built-in profiles are materialized by `granular init` and `granular pull`:
388
+
389
+ - `allow-all`: exposes every declared action unless manifest logic denies it.
390
+ - `confirm-all`: exposes every declared action but requires confirmation.
391
+ - `deny-all`: exposes no executable actions.
392
+
393
+ Manifest-level logic policies live on effects and apply to every profile:
394
+
395
+ ```json
396
+ {
397
+ "withEffect": {
398
+ "name": "approve_ticket",
399
+ "attachedClass": "ticket",
400
+ "inputSchema": { "type": "object", "properties": { "note": { "type": "string" } } },
401
+ "outputSchema": { "type": "object", "properties": { "ok": { "type": "boolean" } } },
402
+ "metamodels": {
403
+ "policies": {
404
+ "denyWhen": [
405
+ {
406
+ "reason": "Locked tickets cannot be approved",
407
+ "when": { "object": { "path": "locked", "operator": "eq", "booleanValue": true } }
408
+ }
409
+ ]
410
+ }
411
+ }
412
+ }
413
+ }
414
+ ```
415
+
416
+ Permission profile files define role-specific access:
417
+
418
+ ```json
419
+ {
420
+ "schemaVersion": 1,
421
+ "name": "reviewer",
422
+ "defaults": { "actionPolicy": "deny" },
423
+ "policies": [
424
+ {
425
+ "action": "approve_ticket",
426
+ "on": "ticket",
427
+ "decision": "allow",
428
+ "reason": "Active low-risk tickets can be approved",
429
+ "when": {
430
+ "all": [
431
+ { "object": { "path": "risk_score", "operator": "lte", "numberValue": 50 } },
432
+ { "stateMachine": { "machine": "lifecycle", "operator": "eq", "stringValue": "active" } }
433
+ ]
434
+ }
435
+ }
436
+ ],
437
+ "actions": [
438
+ { "action": "comment_ticket", "on": "ticket", "allow": "always" }
439
+ ]
440
+ }
441
+ ```
442
+
443
+ Supported profile features:
444
+
445
+ - `defaults.actionPolicy`: `allow`, `confirm`, or `deny` (omitted means `deny`).
446
+ - `extends`: inherit one parent profile; children cannot define `defaults`.
447
+ - `policies[]`: cross-action or targeted rules with `decision` / `outcome` and `when`.
448
+ - `actions[]`: `allow`, `confirm`, `deny`, `allowWhen`, `confirmWhen`, `denyWhen`, and numeric `limits`.
449
+ - Conditions can read `input`, target `object` fields, and target `stateMachine` state, with `all`, `any`, and `not`.
450
+
451
+ Decision precedence is deterministic: manifest deny, profile deny, confirmation rules, profile allow, then the profile default. Runtime blocks denied actions before the effect provider is invoked; confirmation rules use the normal human prompt flow.
452
+
453
+ Useful CLI checks:
454
+
455
+ ```bash
456
+ granular permissions validate
457
+ granular permissions preview --profile reviewer --action approve_ticket --on ticket \
458
+ --input '{"note":"ok"}' \
459
+ --object '{"risk_score":40,"locked":false}' \
460
+ --state-machines '{"lifecycle":"active"}'
461
+ ```
462
+
383
463
  ## Domain Synthesis (Auto-Generated Types)
384
464
 
385
465
  After applying the manifest and publishing tools, the sandbox gets **auto-generated TypeScript classes** in `./sandbox-tools`:
@@ -1,5 +1,6 @@
1
- import { P as Prompt, f as EnvironmentSession, c as SessionHeapSnapshot, bl as ManifestContent, aO as RecordObjectOptions, T as ToolWithHandler, G as Granular, C as ConnectOptions, J as CreateEnvironmentData, k as GranularOptions } from './client-Cq8onk2D.mjs';
2
- import { GeneratedJobCodeIssue, HarnessControllerBudgets } from './agent-harness.mjs';
1
+ import { P as Prompt, f as EnvironmentSession, c as SessionHeapSnapshot, br as ManifestContent, aR as RecordObjectOptions, T as ToolWithHandler, G as Granular, C as ConnectOptions, J as CreateEnvironmentData, k as GranularOptions } from './client-eE9nTfvp.mjs';
2
+ import { GranularAgentToolInfo, GeneratedJobCodeIssue, HarnessControllerBudgets } from './agent-harness.mjs';
3
+ import '@granular-software/policy-engine';
3
4
  import '@automerge/automerge';
4
5
  import '@automerge/automerge/slim';
5
6
 
@@ -19,12 +20,36 @@ interface AgentEvalGenerationInput {
19
20
  }>;
20
21
  request: string;
21
22
  attempt: number;
23
+ tools?: GranularAgentToolInfo[];
22
24
  repairIssues?: GeneratedJobCodeIssue[];
25
+ onTextDelta?: (delta: string) => void | Promise<void>;
23
26
  }
24
27
  interface AgentEvalGenerationOutput {
25
28
  reply?: string;
26
29
  code?: string;
27
30
  raw?: unknown;
31
+ generationAttempts?: AgentEvalGenerationAttempt[];
32
+ }
33
+ interface AgentEvalGenerationAttempt {
34
+ attempt: number;
35
+ request: string;
36
+ repairIssues?: GeneratedJobCodeIssue[];
37
+ reply?: string;
38
+ code?: string;
39
+ raw?: unknown;
40
+ }
41
+ interface AgentEvalTokenUsage {
42
+ calls: number;
43
+ inputTokens: number;
44
+ cachedInputTokens: number;
45
+ uncachedInputTokens: number;
46
+ outputTokens: number;
47
+ totalTokens: number;
48
+ inputCostUsd: number;
49
+ cachedInputCostUsd: number;
50
+ outputCostUsd: number;
51
+ totalCostUsd: number;
52
+ missingUsageCalls: number;
28
53
  }
29
54
  type AgentEvalTurnGenerator = (input: AgentEvalGenerationInput) => Promise<AgentEvalGenerationOutput>;
30
55
  interface ScriptedPromptRule {
@@ -101,6 +126,8 @@ interface AgentEvalStep {
101
126
  }
102
127
  interface AgentEvalScenario {
103
128
  id: string;
129
+ description?: string;
130
+ jobSource?: "llm" | "hardcoded" | "mixed";
104
131
  request?: string;
105
132
  steps?: AgentEvalStep[];
106
133
  setup?: AgentEvalSetup;
@@ -134,6 +161,7 @@ interface AgentEvalResult {
134
161
  actionSummary: string[];
135
162
  promptInteractions: AgentEvalPromptInteraction[];
136
163
  verification: unknown | null;
164
+ tokenUsage?: AgentEvalTokenUsage;
137
165
  steps?: AgentEvalStepResult[];
138
166
  turnDir: string;
139
167
  error?: string;
@@ -164,6 +192,39 @@ interface AgentEvalConversation {
164
192
  promptEvents: PendingPromptEvent[];
165
193
  artifactDir: string;
166
194
  turnCount: number;
195
+ logTurns: AgentEvalSessionLogTurn[];
196
+ }
197
+ interface AgentEvalSessionLogIteration {
198
+ iteration: number;
199
+ request: string;
200
+ systemPrompt: string;
201
+ generationReply?: string;
202
+ generatedCode?: string;
203
+ rawGeneration?: unknown;
204
+ generationAttempts?: AgentEvalGenerationAttempt[];
205
+ tokenUsage?: AgentEvalTokenUsage;
206
+ responseText?: string;
207
+ terminalKind?: "reply" | "closure";
208
+ actionSummary?: string[];
209
+ promptInteractions?: AgentEvalPromptInteraction[];
210
+ continuation?: unknown;
211
+ result?: unknown;
212
+ error?: string;
213
+ }
214
+ interface AgentEvalSessionLogTurn {
215
+ turnNumber: number;
216
+ turnId: string;
217
+ request: string;
218
+ turnDir: string;
219
+ iterations: AgentEvalSessionLogIteration[];
220
+ completed?: {
221
+ responseText: string;
222
+ terminalKind: "reply" | "closure";
223
+ actionSummary: string[];
224
+ promptInteractions: AgentEvalPromptInteraction[];
225
+ result?: unknown;
226
+ };
227
+ error?: string;
167
228
  }
168
229
  interface AgentEvalPendingTurn {
169
230
  conversation: AgentEvalConversation;
@@ -318,4 +379,4 @@ declare const createHumanResponder: typeof createScriptedPromptResponder;
318
379
  declare const createOpenAIGenerator: typeof createOpenAIChatTurnGenerator;
319
380
  declare const createTestArtifactsDirectory: typeof createTimestampedArtifactDirectory;
320
381
 
321
- export { type AgentEvalCheck, type AgentEvalCheckContext, type AgentEvalCompletedTurn, type AgentEvalConversation, type AgentEvalExpectations, type AgentEvalGenerationInput, type AgentEvalGenerationOutput, type AgentEvalHarnessOptions, type AgentEvalInspection, type AgentEvalPendingTurn, type AgentEvalPrepareContext, type AgentEvalPromptInteraction, type AgentEvalPromptResponder, type AgentEvalResult, type AgentEvalScenario, type AgentEvalSetup, type AgentEvalSetupContext, type AgentEvalStep, type AgentEvalStepResult, type AgentEvalSuiteResult, type AgentEvalTurnGenerator, type AgentTestTarget, type AgentTesterOptions, type EvalMatcher, type ScriptedPromptRule, createAgentEvalHarness, createAgentTester, createHumanResponder, createOpenAIChatTurnGenerator, createOpenAIGenerator, createScriptedPromptResponder, createTestArtifactsDirectory, createTimestampedArtifactDirectory, runAgentEvalSuite, runAgentTests };
382
+ export { type AgentEvalCheck, type AgentEvalCheckContext, type AgentEvalCompletedTurn, type AgentEvalConversation, type AgentEvalExpectations, type AgentEvalGenerationAttempt, type AgentEvalGenerationInput, type AgentEvalGenerationOutput, type AgentEvalHarnessOptions, type AgentEvalInspection, type AgentEvalPendingTurn, type AgentEvalPrepareContext, type AgentEvalPromptInteraction, type AgentEvalPromptResponder, type AgentEvalResult, type AgentEvalScenario, type AgentEvalSetup, type AgentEvalSetupContext, type AgentEvalStep, type AgentEvalStepResult, type AgentEvalSuiteResult, type AgentEvalTokenUsage, type AgentEvalTurnGenerator, type AgentTestTarget, type AgentTesterOptions, type EvalMatcher, type ScriptedPromptRule, createAgentEvalHarness, createAgentTester, createHumanResponder, createOpenAIChatTurnGenerator, createOpenAIGenerator, createScriptedPromptResponder, createTestArtifactsDirectory, createTimestampedArtifactDirectory, runAgentEvalSuite, runAgentTests };
@@ -1,5 +1,6 @@
1
- import { P as Prompt, f as EnvironmentSession, c as SessionHeapSnapshot, bl as ManifestContent, aO as RecordObjectOptions, T as ToolWithHandler, G as Granular, C as ConnectOptions, J as CreateEnvironmentData, k as GranularOptions } from './client-Cq8onk2D.js';
2
- import { GeneratedJobCodeIssue, HarnessControllerBudgets } from './agent-harness.js';
1
+ import { P as Prompt, f as EnvironmentSession, c as SessionHeapSnapshot, br as ManifestContent, aR as RecordObjectOptions, T as ToolWithHandler, G as Granular, C as ConnectOptions, J as CreateEnvironmentData, k as GranularOptions } from './client-eE9nTfvp.js';
2
+ import { GranularAgentToolInfo, GeneratedJobCodeIssue, HarnessControllerBudgets } from './agent-harness.js';
3
+ import '@granular-software/policy-engine';
3
4
  import '@automerge/automerge';
4
5
  import '@automerge/automerge/slim';
5
6
 
@@ -19,12 +20,36 @@ interface AgentEvalGenerationInput {
19
20
  }>;
20
21
  request: string;
21
22
  attempt: number;
23
+ tools?: GranularAgentToolInfo[];
22
24
  repairIssues?: GeneratedJobCodeIssue[];
25
+ onTextDelta?: (delta: string) => void | Promise<void>;
23
26
  }
24
27
  interface AgentEvalGenerationOutput {
25
28
  reply?: string;
26
29
  code?: string;
27
30
  raw?: unknown;
31
+ generationAttempts?: AgentEvalGenerationAttempt[];
32
+ }
33
+ interface AgentEvalGenerationAttempt {
34
+ attempt: number;
35
+ request: string;
36
+ repairIssues?: GeneratedJobCodeIssue[];
37
+ reply?: string;
38
+ code?: string;
39
+ raw?: unknown;
40
+ }
41
+ interface AgentEvalTokenUsage {
42
+ calls: number;
43
+ inputTokens: number;
44
+ cachedInputTokens: number;
45
+ uncachedInputTokens: number;
46
+ outputTokens: number;
47
+ totalTokens: number;
48
+ inputCostUsd: number;
49
+ cachedInputCostUsd: number;
50
+ outputCostUsd: number;
51
+ totalCostUsd: number;
52
+ missingUsageCalls: number;
28
53
  }
29
54
  type AgentEvalTurnGenerator = (input: AgentEvalGenerationInput) => Promise<AgentEvalGenerationOutput>;
30
55
  interface ScriptedPromptRule {
@@ -101,6 +126,8 @@ interface AgentEvalStep {
101
126
  }
102
127
  interface AgentEvalScenario {
103
128
  id: string;
129
+ description?: string;
130
+ jobSource?: "llm" | "hardcoded" | "mixed";
104
131
  request?: string;
105
132
  steps?: AgentEvalStep[];
106
133
  setup?: AgentEvalSetup;
@@ -134,6 +161,7 @@ interface AgentEvalResult {
134
161
  actionSummary: string[];
135
162
  promptInteractions: AgentEvalPromptInteraction[];
136
163
  verification: unknown | null;
164
+ tokenUsage?: AgentEvalTokenUsage;
137
165
  steps?: AgentEvalStepResult[];
138
166
  turnDir: string;
139
167
  error?: string;
@@ -164,6 +192,39 @@ interface AgentEvalConversation {
164
192
  promptEvents: PendingPromptEvent[];
165
193
  artifactDir: string;
166
194
  turnCount: number;
195
+ logTurns: AgentEvalSessionLogTurn[];
196
+ }
197
+ interface AgentEvalSessionLogIteration {
198
+ iteration: number;
199
+ request: string;
200
+ systemPrompt: string;
201
+ generationReply?: string;
202
+ generatedCode?: string;
203
+ rawGeneration?: unknown;
204
+ generationAttempts?: AgentEvalGenerationAttempt[];
205
+ tokenUsage?: AgentEvalTokenUsage;
206
+ responseText?: string;
207
+ terminalKind?: "reply" | "closure";
208
+ actionSummary?: string[];
209
+ promptInteractions?: AgentEvalPromptInteraction[];
210
+ continuation?: unknown;
211
+ result?: unknown;
212
+ error?: string;
213
+ }
214
+ interface AgentEvalSessionLogTurn {
215
+ turnNumber: number;
216
+ turnId: string;
217
+ request: string;
218
+ turnDir: string;
219
+ iterations: AgentEvalSessionLogIteration[];
220
+ completed?: {
221
+ responseText: string;
222
+ terminalKind: "reply" | "closure";
223
+ actionSummary: string[];
224
+ promptInteractions: AgentEvalPromptInteraction[];
225
+ result?: unknown;
226
+ };
227
+ error?: string;
167
228
  }
168
229
  interface AgentEvalPendingTurn {
169
230
  conversation: AgentEvalConversation;
@@ -318,4 +379,4 @@ declare const createHumanResponder: typeof createScriptedPromptResponder;
318
379
  declare const createOpenAIGenerator: typeof createOpenAIChatTurnGenerator;
319
380
  declare const createTestArtifactsDirectory: typeof createTimestampedArtifactDirectory;
320
381
 
321
- export { type AgentEvalCheck, type AgentEvalCheckContext, type AgentEvalCompletedTurn, type AgentEvalConversation, type AgentEvalExpectations, type AgentEvalGenerationInput, type AgentEvalGenerationOutput, type AgentEvalHarnessOptions, type AgentEvalInspection, type AgentEvalPendingTurn, type AgentEvalPrepareContext, type AgentEvalPromptInteraction, type AgentEvalPromptResponder, type AgentEvalResult, type AgentEvalScenario, type AgentEvalSetup, type AgentEvalSetupContext, type AgentEvalStep, type AgentEvalStepResult, type AgentEvalSuiteResult, type AgentEvalTurnGenerator, type AgentTestTarget, type AgentTesterOptions, type EvalMatcher, type ScriptedPromptRule, createAgentEvalHarness, createAgentTester, createHumanResponder, createOpenAIChatTurnGenerator, createOpenAIGenerator, createScriptedPromptResponder, createTestArtifactsDirectory, createTimestampedArtifactDirectory, runAgentEvalSuite, runAgentTests };
382
+ export { type AgentEvalCheck, type AgentEvalCheckContext, type AgentEvalCompletedTurn, type AgentEvalConversation, type AgentEvalExpectations, type AgentEvalGenerationAttempt, type AgentEvalGenerationInput, type AgentEvalGenerationOutput, type AgentEvalHarnessOptions, type AgentEvalInspection, type AgentEvalPendingTurn, type AgentEvalPrepareContext, type AgentEvalPromptInteraction, type AgentEvalPromptResponder, type AgentEvalResult, type AgentEvalScenario, type AgentEvalSetup, type AgentEvalSetupContext, type AgentEvalStep, type AgentEvalStepResult, type AgentEvalSuiteResult, type AgentEvalTokenUsage, type AgentEvalTurnGenerator, type AgentTestTarget, type AgentTesterOptions, type EvalMatcher, type ScriptedPromptRule, createAgentEvalHarness, createAgentTester, createHumanResponder, createOpenAIChatTurnGenerator, createOpenAIGenerator, createScriptedPromptResponder, createTestArtifactsDirectory, createTimestampedArtifactDirectory, runAgentEvalSuite, runAgentTests };