@arnilo/prism 0.5.6 → 0.7.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 (160) hide show
  1. package/CHANGELOG.md +81 -5
  2. package/README.md +10 -10
  3. package/dist/agent-approval.js +7 -6
  4. package/dist/agent-definitions.js +1 -0
  5. package/dist/agent-loops.js +51 -12
  6. package/dist/agent-run-lifecycle.js +11 -0
  7. package/dist/agent-run-state.d.ts +6 -0
  8. package/dist/agent-run-state.js +29 -9
  9. package/dist/agent-session/session/assemble.js +33 -2
  10. package/dist/agent-session/session/persist.js +6 -2
  11. package/dist/agent-session/session/tool-round.js +1 -0
  12. package/dist/agent-session/session/types.d.ts +10 -0
  13. package/dist/agent-session/session.d.ts +15 -0
  14. package/dist/agent-session/session.js +59 -4
  15. package/dist/agent-tool-dispatch.js +5 -4
  16. package/dist/artifacts.d.ts +39 -1
  17. package/dist/artifacts.js +73 -0
  18. package/dist/attention-compiler.d.ts +121 -0
  19. package/dist/attention-compiler.js +479 -0
  20. package/dist/cli-init.js +20 -6
  21. package/dist/content.d.ts +3 -16
  22. package/dist/content.js +9 -99
  23. package/dist/context-budget.d.ts +32 -2
  24. package/dist/context-budget.js +51 -19
  25. package/dist/contracts-core/agent.d.ts +18 -0
  26. package/dist/contracts-core/agent.js +4 -1
  27. package/dist/contracts-core/attention.d.ts +66 -0
  28. package/dist/contracts-core/attention.js +2 -0
  29. package/dist/contracts-core/compaction.d.ts +59 -0
  30. package/dist/contracts-core/compaction.js +77 -1
  31. package/dist/contracts-core/provider.d.ts +4 -0
  32. package/dist/contracts-core.d.ts +1 -0
  33. package/dist/contracts-core.js +1 -0
  34. package/dist/contracts-protocol.d.ts +29 -0
  35. package/dist/contracts-run-state.d.ts +6 -0
  36. package/dist/host-composition.d.ts +78 -0
  37. package/dist/host-composition.js +248 -0
  38. package/dist/index.d.ts +11 -8
  39. package/dist/index.js +6 -5
  40. package/dist/input.d.ts +19 -1
  41. package/dist/input.js +52 -2
  42. package/dist/media-types.d.ts +34 -0
  43. package/dist/media-types.js +158 -0
  44. package/dist/pinned-fetch.d.ts +2 -2
  45. package/dist/pinned-fetch.js +11 -12
  46. package/dist/redaction.js +74 -1
  47. package/dist/secure-agent.d.ts +2 -0
  48. package/dist/secure-agent.js +6 -1
  49. package/dist/session-stores.d.ts +11 -0
  50. package/dist/session-stores.js +23 -8
  51. package/dist/tool-result-fold.d.ts +12 -0
  52. package/dist/tool-result-fold.js +13 -6
  53. package/dist/tools.d.ts +10 -0
  54. package/dist/tools.js +41 -0
  55. package/docs/acp-agent.md +42 -11
  56. package/docs/acp.md +3 -2
  57. package/docs/ag-ui.md +9 -5
  58. package/docs/agent-definitions.md +9 -1
  59. package/docs/agent-events.md +6 -1
  60. package/docs/agent-loops.md +1 -1
  61. package/docs/agent-session-runtime.md +9 -7
  62. package/docs/attention-compiler.md +272 -0
  63. package/docs/browser-automation.md +5 -2
  64. package/docs/cli-rpc.md +4 -2
  65. package/docs/coding-agent-tools.md +1 -1
  66. package/docs/coding-security.md +5 -3
  67. package/docs/coding-tools.md +1 -1
  68. package/docs/coding-workspaces.md +22 -0
  69. package/docs/compaction-and-retry.md +36 -4
  70. package/docs/compaction-observational-memory.md +62 -9
  71. package/docs/context-and-skills.md +4 -2
  72. package/docs/contributing.md +37 -0
  73. package/docs/conversations.md +1 -1
  74. package/docs/core.md +2 -0
  75. package/docs/dev-inspector.md +4 -0
  76. package/docs/device-adapters.md +1 -0
  77. package/docs/document-reader.md +12 -2
  78. package/docs/documents.md +11 -3
  79. package/docs/enterprise-postgres-state.md +2 -2
  80. package/docs/evaluations.md +168 -4
  81. package/docs/execution-timeline.md +180 -0
  82. package/docs/graft.md +3 -1
  83. package/docs/history/0.7.0-primitive-review.md +254 -0
  84. package/docs/history/migration-0.0.md +2 -2
  85. package/docs/history/release-handoffs.md +70 -1
  86. package/docs/host-compositions.md +147 -0
  87. package/docs/host-security.md +2 -2
  88. package/docs/hosted-sandboxes.md +94 -0
  89. package/docs/index.md +73 -41
  90. package/docs/input-and-prompt-assembly.md +5 -4
  91. package/docs/knowledge-sync.md +84 -0
  92. package/docs/language-intelligence.md +2 -2
  93. package/docs/live-testing.md +4 -1
  94. package/docs/mcp-tools.md +2 -1
  95. package/docs/memory-fabric.md +416 -0
  96. package/docs/migrate-to-0.5.md +8 -3
  97. package/docs/migrate-to-0.6.md +90 -0
  98. package/docs/migrate-to-0.7.md +345 -0
  99. package/docs/migration.md +43 -1
  100. package/docs/model-registry.md +1 -1
  101. package/docs/model-routing.md +79 -4
  102. package/docs/multi-agent-patterns.md +20 -6
  103. package/docs/multimodal-content.md +1 -1
  104. package/docs/obscura.md +3 -1
  105. package/docs/observability.md +52 -1
  106. package/docs/operations.md +13 -1
  107. package/docs/options-index.md +298 -0
  108. package/docs/peer-dependencies.md +96 -0
  109. package/docs/performance.md +34 -2
  110. package/docs/ponytail.md +2 -0
  111. package/docs/postgres-persistence.md +3 -1
  112. package/docs/process-sessions.md +3 -1
  113. package/docs/prompt-registry.md +1 -1
  114. package/docs/provider-caching.md +4 -2
  115. package/docs/provider-conformance.md +2 -2
  116. package/docs/provider-packages.md +23 -23
  117. package/docs/provider-primitives.md +2 -1
  118. package/docs/providers/ai-sdk.md +5 -2
  119. package/docs/providers/bedrock.md +71 -7
  120. package/docs/providers/openai.md +1 -1
  121. package/docs/public-contracts.md +2 -2
  122. package/docs/rag.md +24 -8
  123. package/docs/realtime-voice.md +87 -0
  124. package/docs/release-and-install.md +78 -56
  125. package/docs/runs-and-usage.md +3 -2
  126. package/docs/server.md +6 -4
  127. package/docs/session-stores.md +3 -1
  128. package/docs/speech.md +2 -0
  129. package/docs/sqlite-persistence.md +2 -0
  130. package/docs/supervisors.md +33 -5
  131. package/docs/testing.md +38 -0
  132. package/docs/thinking-and-reasoning.md +3 -1
  133. package/docs/tools.md +7 -6
  134. package/docs/web-tools.md +2 -1
  135. package/docs/wiki.md +1 -1
  136. package/docs/work-artifacts-and-review.md +14 -4
  137. package/docs/work-connectors.md +3 -1
  138. package/docs/work-tools.md +14 -4
  139. package/docs/workflows.md +69 -1
  140. package/docs/working-and-semantic-memory.md +25 -14
  141. package/package.json +5 -5
  142. package/templates/README.md +2 -0
  143. package/templates/business-worker/README.md.tmpl +19 -0
  144. package/templates/business-worker/env.example.tmpl +1 -0
  145. package/templates/business-worker/gitignore.tmpl +11 -0
  146. package/templates/business-worker/manifest.json +11 -0
  147. package/templates/business-worker/package.json.tmpl +23 -0
  148. package/templates/business-worker/src/agent.ts.tmpl +92 -0
  149. package/templates/business-worker/src/index.ts.tmpl +13 -0
  150. package/templates/business-worker/src/tests/agent.test.ts.tmpl +77 -0
  151. package/templates/business-worker/tsconfig.json.tmpl +15 -0
  152. package/templates/personal-assistant/README.md.tmpl +18 -0
  153. package/templates/personal-assistant/env.example.tmpl +1 -0
  154. package/templates/personal-assistant/gitignore.tmpl +11 -0
  155. package/templates/personal-assistant/manifest.json +11 -0
  156. package/templates/personal-assistant/package.json.tmpl +23 -0
  157. package/templates/personal-assistant/src/agent.ts.tmpl +65 -0
  158. package/templates/personal-assistant/src/index.ts.tmpl +13 -0
  159. package/templates/personal-assistant/src/tests/agent.test.ts.tmpl +28 -0
  160. package/templates/personal-assistant/tsconfig.json.tmpl +15 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arnilo/prism",
3
- "version": "0.5.6",
3
+ "version": "0.7.0",
4
4
  "description": "Agent harness for AI providers, agents, sessions, and tools.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -139,7 +139,7 @@
139
139
  "typecheck": "npm run build && npm run typecheck --workspaces --if-present && tsc -p examples --noEmit",
140
140
  "sweep:unused": "node scripts/sweep-unused.mjs --json",
141
141
  "test:live": "node scripts/live-matrix.mjs",
142
- "test": "npm run build && node scripts/with-build-lock.mjs node --test dist/__tests__/*.test.js && node scripts/with-build-lock.mjs node --test scripts/release-gate.test.mjs scripts/tooling-gate.test.mjs scripts/budget-gate.test.mjs scripts/phase8-conformance.test.mjs scripts/phase9-conformance.test.mjs scripts/phase10-conformance.test.mjs scripts/phase11-conformance.test.mjs scripts/benchmark-0.1.0.test.mjs scripts/benchmark-multi-agent.test.mjs scripts/benchmark-tool-search.test.mjs scripts/benchmark-workflow-loop.test.mjs scripts/sweep-unused.test.mjs scripts/dead-export-verify.test.mjs scripts/e2e-enterprise-journey.test.mjs scripts/e2e-coding-journey.test.mjs scripts/e2e-full-surface.test.mjs scripts/phase23-quality-gates.test.mjs scripts/phase24-truth.test.mjs scripts/phase25-bounded-accumulation.test.mjs scripts/phase27-ha.test.mjs scripts/phase27-erp-journey.test.mjs scripts/phase37-provider-matrix.test.mjs scripts/phase26-index-benchmark.test.mjs scripts/obscura-host-conformance.test.mjs scripts/phase54-package-map.test.mjs scripts/phase54-legacy-registry.test.mjs scripts/truth-current.test.mjs scripts/packaging-current.test.mjs scripts/import-hygiene.test.mjs scripts/live-matrix.test.mjs scripts/e2e-coverage.test.mjs scripts/live-doc-check.test.mjs && node --test scripts/phase23-build-race.test.mjs && npm run test --workspaces --if-present",
142
+ "test": "node scripts/run-all-tests.mjs",
143
143
  "test:coverage": "node scripts/with-build-lock.mjs node --test --experimental-test-coverage --test-coverage-lines=60 --test-coverage-functions=70 --test-coverage-branches=75 --test-coverage-exclude='**/__tests__/**' --test-coverage-exclude='**/node_modules/**' --test-coverage-exclude='**/scripts/**' --test-coverage-exclude='**/packages/**' --test-coverage-exclude='**/examples/**' dist/__tests__/*.test.js && node scripts/with-build-lock.mjs node scripts/coverage-summary.mjs && node --test scripts/phase23-coverage.test.mjs && node --test scripts/phase23-skip-manifest.test.mjs",
144
144
  "coverage:summary": "node scripts/with-build-lock.mjs node scripts/coverage-summary.mjs",
145
145
  "lint": "biome lint . --reporter=sarif --reporter-file=scripts/lint-report.sarif",
@@ -157,12 +157,12 @@
157
157
  "security:threat-suites": "node --test scripts/phase8-conformance.test.mjs scripts/phase9-conformance.test.mjs scripts/phase10-conformance.test.mjs scripts/phase11-conformance.test.mjs scripts/phase20-security.test.mjs scripts/phase21-security.test.mjs scripts/phase22-security.test.mjs scripts/phase23-security.test.mjs scripts/phase38-codeql-regression.test.mjs scripts/phase40-security.test.mjs scripts/phase46-webhooks-security.test.mjs dist/__tests__/pinned-fetch.test.js packages/prism-core/dist/runtime/server/__tests__/webhooks.test.js"
158
158
  },
159
159
  "devDependencies": {
160
- "@biomejs/biome": "^2.5.11",
161
- "@types/node": "^26.1.1",
160
+ "@biomejs/biome": "^2.5.13",
161
+ "@types/node": "^22.20.0",
162
162
  "typescript": "^7.0.2"
163
163
  },
164
164
  "engines": {
165
- "node": ">=20"
165
+ "node": ">=22"
166
166
  },
167
167
  "license": "MIT",
168
168
  "repository": {
@@ -8,6 +8,8 @@ Ready-to-run project templates for `prism init --template <name>`.
8
8
  | --- | --- | --- |
9
9
  | `init` | Minimal starter Prism agent with one selected provider and offline mock test | `@arnilo/prism` |
10
10
  | `deep-research` | Flagship deep research agent: plan -> search -> extract -> refine loop -> citations -> HITL clarify | `@arnilo/prism`, `@arnilo/prism-web-tools`, `@arnilo/prism-memory`, `@arnilo/prism-workflows` |
11
+ | `personal-assistant` | Personal workstation assistant: single-user ownership, local tools, credential references, and dev inspection | `@arnilo/prism`, `@arnilo/prism-core`, `@arnilo/prism-providers` |
12
+ | `business-worker` | Multi-tenant business worker: durable storage, tenant isolation, verified identity, and governed boundaries | `@arnilo/prism`, `@arnilo/prism-core`, `@arnilo/prism-providers` |
11
13
 
12
14
  ## Usage
13
15
 
@@ -0,0 +1,19 @@
1
+ # __PROJECT_NAME__
2
+
3
+ Multi-tenant business worker built with Prism. Features strict tenant isolation, verified identities, durable persistence, and governed invocation boundaries.
4
+
5
+ ## Quickstart
6
+
7
+ ```bash
8
+ npm install
9
+ npm test
10
+ npm start
11
+ ```
12
+
13
+ ## Production Readiness Requirements
14
+
15
+ - **Tenant Isolation**: Non-empty `tenantId` in ownership; tenant-scoped stores and workspaces.
16
+ - **Verified Identity**: Host-verified principal matching tenant ownership; no fabricated identities.
17
+ - **Durable Persistence**: Production readiness strictly rejects in-memory stores; PostgreSQL or SQLite durable stores required.
18
+ - **Workspace Containment**: Execution confined to authorized tenant sandbox directories.
19
+ - **Governed Invocation**: Permission policies, trust verification, parameter validation, and secret redaction enforced.
@@ -0,0 +1 @@
1
+ BUSINESS_API_KEY=
@@ -0,0 +1,11 @@
1
+ node_modules/
2
+ dist/
3
+ .env
4
+ .env.local
5
+ *.db
6
+ *.sqlite
7
+ *.sqlite3
8
+ .prism/
9
+ coverage/
10
+ .DS_Store
11
+ *.log
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "business-worker",
3
+ "description": "Multi-tenant business worker: durable storage, tenant isolation, verified identity, and governed invocation boundaries",
4
+ "version": "0.1.0",
5
+ "tags": ["business", "worker", "multi-tenant", "enterprise", "secure"],
6
+ "packages": [
7
+ "@arnilo/prism",
8
+ "@arnilo/prism-core",
9
+ "@arnilo/prism-providers"
10
+ ]
11
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "__PROJECT_NAME__",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "build": "tsc -p tsconfig.json",
8
+ "typecheck": "tsc -p tsconfig.json --noEmit",
9
+ "test": "npm run build && node --test dist/__tests__/agent.test.js",
10
+ "start": "npm run build && node dist/index.js",
11
+ "dev": "prism dev"
12
+ },
13
+ "dependencies": {
14
+ __DEPENDENCIES__
15
+ },
16
+ "devDependencies": {
17
+ "@types/node": "^22.0.0",
18
+ "typescript": "^5.7.0"
19
+ },
20
+ "engines": {
21
+ "node": ">=20"
22
+ }
23
+ }
@@ -0,0 +1,92 @@
1
+ import {
2
+ type Agent,
3
+ createMemoryCheckpointStore,
4
+ createMockProvider,
5
+ createSecretRedactor,
6
+ createSecureAgent,
7
+ createStaticPermissionPolicy,
8
+ createStaticTrustPolicy,
9
+ providerDone,
10
+ providerTextDelta,
11
+ } from "@arnilo/prism";
12
+ import { createJsonSchemaArgumentValidator } from "@arnilo/prism-core/validation/json-schema";
13
+ import { createMemoryWorkDraftStore, type SyncWorkDraftStore } from "@arnilo/prism-core/integrations/work";
14
+ import type { AgentIdentity } from "@arnilo/prism";
15
+
16
+ export interface CreateBusinessWorkerOptions {
17
+ readonly tenantId?: string;
18
+ readonly userId?: string;
19
+ readonly identity?: AgentIdentity;
20
+ readonly store?: import("@arnilo/prism").CheckpointStore;
21
+ readonly provider?: import("@arnilo/prism").AIProvider;
22
+ readonly model?: { readonly provider: string; readonly model: string };
23
+ readonly workspaceRoot?: string;
24
+ }
25
+
26
+ export function createAppAgent(options: CreateBusinessWorkerOptions = {}): Agent {
27
+ const tenantId = options.tenantId ?? "tenant-corp";
28
+ const userId = options.userId ?? "worker-1";
29
+
30
+ const identity: AgentIdentity = options.identity ?? {
31
+ tenantId,
32
+ userId,
33
+ principal: { kind: "user", id: userId },
34
+ scopes: ["worker:execute"],
35
+ verified: true,
36
+ issuedAt: new Date().toISOString(),
37
+ };
38
+
39
+ const redactor = createSecretRedactor(
40
+ [process.env.BUSINESS_API_KEY].filter((v): v is string => typeof v === "string" && v.length > 0),
41
+ );
42
+
43
+ const provider =
44
+ options.provider ??
45
+ createMockProvider([
46
+ providerTextDelta("Business worker ready for tenant tasks."),
47
+ providerDone(),
48
+ ]);
49
+
50
+ return createSecureAgent({
51
+ id: "business-worker",
52
+ definitionRevision: "1",
53
+ ownership: { tenantId, userId },
54
+ identity,
55
+ redactor,
56
+ permission: createStaticPermissionPolicy(true),
57
+ trust: createStaticTrustPolicy(true),
58
+ toolArgumentValidator: createJsonSchemaArgumentValidator(),
59
+ limits: { maxToolRounds: 15 },
60
+ runState: { checkpoints: options.store ?? createMemoryCheckpointStore() },
61
+ tools: [
62
+ {
63
+ name: "process_tenant_record",
64
+ description: "Processes a verified tenant batch item",
65
+ parameters: {
66
+ type: "object",
67
+ properties: {
68
+ recordId: { type: "string" },
69
+ action: { type: "string" },
70
+ },
71
+ required: ["recordId", "action"],
72
+ additionalProperties: false,
73
+ },
74
+ execute: async (args, ctx) => ({
75
+ toolCallId: ctx.toolCallId,
76
+ name: "process_tenant_record",
77
+ value: {
78
+ processed: true,
79
+ tenantId,
80
+ recordId: (args as { recordId: string }).recordId,
81
+ },
82
+ }),
83
+ },
84
+ ],
85
+ provider,
86
+ model: options.model ?? { provider: "mock", model: "corp-worker-model" },
87
+ });
88
+ }
89
+
90
+ export function createWorkerDraftStore(): SyncWorkDraftStore {
91
+ return createMemoryWorkDraftStore();
92
+ }
@@ -0,0 +1,13 @@
1
+ import { createAppAgent } from "./agent.js";
2
+
3
+ async function main() {
4
+ const agent = createAppAgent({ tenantId: "tenant-acme", userId: "worker-prod-1" });
5
+ const session = agent.createSession({ id: "biz-session-1" });
6
+ const result = await session.run("Process batch queue item");
7
+ console.log(result.text);
8
+ }
9
+
10
+ main().catch((error) => {
11
+ console.error("Business worker failed:", error);
12
+ process.exit(1);
13
+ });
@@ -0,0 +1,77 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { assertHostCompositionReadiness, inspectHostComposition, HostCompositionError } from "@arnilo/prism";
4
+ import { validateApproval } from "@arnilo/prism-core/integrations/work";
5
+ import type { AgentIdentity } from "@arnilo/prism";
6
+ import { createAppAgent, createWorkerDraftStore } from "../agent.js";
7
+
8
+ describe("business worker template", () => {
9
+ it("creates agent and processes task with tenant context", async () => {
10
+ const agent = createAppAgent({ tenantId: "tenant-enterprise", userId: "worker-test" });
11
+ const session = agent.createSession({ id: "test-biz-session" });
12
+ const result = await session.run("Run tenant task");
13
+ assert.ok(result.text.includes("Business worker ready"));
14
+ });
15
+
16
+ it("fails business readiness if memory-only store is configured", () => {
17
+ const agent = createAppAgent({ tenantId: "tenant-enterprise", userId: "worker-test" });
18
+ assert.throws(
19
+ () => {
20
+ assertHostCompositionReadiness({
21
+ profile: "business",
22
+ agent,
23
+ store: { kind: "memory", durable: false },
24
+ });
25
+ },
26
+ (error) => error instanceof HostCompositionError && error.message.includes("durable storage"),
27
+ );
28
+ });
29
+
30
+ it("passes business readiness with durable store and isolated workspace", () => {
31
+ const agent = createAppAgent({ tenantId: "tenant-enterprise", userId: "worker-test" });
32
+ const report = inspectHostComposition({
33
+ profile: "business",
34
+ agent,
35
+ store: { kind: "postgres", durable: true },
36
+ workspaceRoot: "/var/tenant-enterprise",
37
+ sandboxRoots: ["/var/tenant-enterprise/tasks"],
38
+ credentialRefs: ["BUSINESS_API_KEY"],
39
+ });
40
+
41
+ assert.equal(report.profile, "business");
42
+ assert.equal(report.ownership.tenantId, "tenant-enterprise");
43
+ assert.equal(report.storage.durable, true);
44
+ assert.equal(report.sandbox.isolated, true);
45
+ assert.equal(report.readiness.ok, true);
46
+ });
47
+
48
+ it("rejects a stale draft revision after edit", () => {
49
+ const store = createWorkerDraftStore();
50
+ const identity: AgentIdentity = {
51
+ tenantId: "tenant-enterprise",
52
+ userId: "worker-test",
53
+ principal: { kind: "user", id: "worker-test" },
54
+ scopes: ["Mail.Send"],
55
+ issuedAt: new Date().toISOString(),
56
+ verified: true,
57
+ };
58
+ const draft = store.createDraft({
59
+ provider: "microsoft365",
60
+ op: "mail.send",
61
+ identity,
62
+ payload: { to: "a@contoso.com", subject: "v1" },
63
+ });
64
+ const approval = {
65
+ draftId: draft.draftId,
66
+ revision: draft.revision,
67
+ payloadDigest: draft.payloadDigest,
68
+ };
69
+ const updated = store.updateDraft({
70
+ draftId: draft.draftId,
71
+ identity,
72
+ payload: { to: "a@contoso.com", subject: "v2" },
73
+ expectedRevision: 1,
74
+ });
75
+ assert.throws(() => validateApproval(updated, approval), /does not match draft revision/);
76
+ });
77
+ });
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "strict": true,
7
+ "outDir": "dist",
8
+ "rootDir": "src",
9
+ "declaration": true,
10
+ "skipLibCheck": true,
11
+ "esModuleInterop": true,
12
+ "forceConsistentCasingInFileNames": true
13
+ },
14
+ "include": ["src"]
15
+ }
@@ -0,0 +1,18 @@
1
+ # __PROJECT_NAME__
2
+
3
+ Personal workstation assistant built with Prism. Features single-user ownership, local tools, credential references, and loopback dev inspection.
4
+
5
+ ## Quickstart
6
+
7
+ ```bash
8
+ npm install
9
+ npm test
10
+ npm run dev # Boots loopback dev inspector at http://127.0.0.1:4311
11
+ ```
12
+
13
+ ## Security Posture
14
+
15
+ - **Single-User Ownership**: Bounded to the local workstation operator (`userId: process.env.USER`).
16
+ - **Secret Redaction**: Environment secrets are redacted before persistence or logs.
17
+ - **Durable Verification**: Uses memory/local storage; in-memory storage is recognized as non-durable.
18
+ - **Containment**: Tool actions are contained to local workspace roots.
@@ -0,0 +1 @@
1
+ OPENAI_API_KEY=
@@ -0,0 +1,11 @@
1
+ node_modules/
2
+ dist/
3
+ .env
4
+ .env.local
5
+ *.db
6
+ *.sqlite
7
+ *.sqlite3
8
+ .prism/
9
+ coverage/
10
+ .DS_Store
11
+ *.log
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "personal-assistant",
3
+ "description": "Personal workstation assistant: local single-user agent with file tools, credential references, and loopback dev inspection",
4
+ "version": "0.1.0",
5
+ "tags": ["personal", "workstation", "assistant", "local", "secure"],
6
+ "packages": [
7
+ "@arnilo/prism",
8
+ "@arnilo/prism-core",
9
+ "@arnilo/prism-providers"
10
+ ]
11
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "__PROJECT_NAME__",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "build": "tsc -p tsconfig.json",
8
+ "typecheck": "tsc -p tsconfig.json --noEmit",
9
+ "test": "npm run build && node --test dist/__tests__/agent.test.js",
10
+ "start": "npm run build && node dist/index.js",
11
+ "dev": "prism dev"
12
+ },
13
+ "dependencies": {
14
+ __DEPENDENCIES__
15
+ },
16
+ "devDependencies": {
17
+ "@types/node": "^22.0.0",
18
+ "typescript": "^5.7.0"
19
+ },
20
+ "engines": {
21
+ "node": ">=20"
22
+ }
23
+ }
@@ -0,0 +1,65 @@
1
+ import {
2
+ type Agent,
3
+ createMemoryCheckpointStore,
4
+ createMockProvider,
5
+ createSecretRedactor,
6
+ createSecureAgent,
7
+ createStaticPermissionPolicy,
8
+ createStaticTrustPolicy,
9
+ providerDone,
10
+ providerTextDelta,
11
+ } from "@arnilo/prism";
12
+ import { createJsonSchemaArgumentValidator } from "@arnilo/prism-core/validation/json-schema";
13
+
14
+ export interface CreatePersonalAgentOptions {
15
+ readonly userId?: string;
16
+ readonly provider?: import("@arnilo/prism").AIProvider;
17
+ readonly model?: { readonly provider: string; readonly model: string };
18
+ readonly workspaceRoot?: string;
19
+ }
20
+
21
+ export function createAppAgent(options: CreatePersonalAgentOptions = {}): Agent {
22
+ const userId = options.userId ?? process.env.USER ?? "local-user";
23
+ const redactor = createSecretRedactor(
24
+ [process.env.OPENAI_API_KEY].filter((v): v is string => typeof v === "string" && v.length > 0),
25
+ );
26
+
27
+ const provider =
28
+ options.provider ??
29
+ createMockProvider([
30
+ providerTextDelta("Personal Assistant ready. How can I help you today?"),
31
+ providerDone(),
32
+ ]);
33
+
34
+ return createSecureAgent({
35
+ id: "personal-assistant",
36
+ definitionRevision: "1",
37
+ ownership: { userId },
38
+ redactor,
39
+ permission: createStaticPermissionPolicy(true),
40
+ trust: createStaticTrustPolicy(true),
41
+ toolArgumentValidator: createJsonSchemaArgumentValidator(),
42
+ limits: { maxToolRounds: 10 },
43
+ runState: { checkpoints: createMemoryCheckpointStore() },
44
+ tools: [
45
+ {
46
+ name: "workspace_status",
47
+ description: "Reports the local workspace status and configuration",
48
+ parameters: {
49
+ type: "object",
50
+ properties: {
51
+ details: { type: "boolean", description: "Include detailed status" },
52
+ },
53
+ additionalProperties: false,
54
+ },
55
+ execute: async (_args, ctx) => ({
56
+ toolCallId: ctx.toolCallId,
57
+ name: "workspace_status",
58
+ value: { ok: true, user: userId, status: "active" },
59
+ }),
60
+ },
61
+ ],
62
+ provider,
63
+ model: options.model ?? { provider: "mock", model: "personal-default" },
64
+ });
65
+ }
@@ -0,0 +1,13 @@
1
+ import { createAppAgent } from "./agent.js";
2
+
3
+ async function main() {
4
+ const agent = createAppAgent();
5
+ const session = agent.createSession({ id: "personal-session-1" });
6
+ const result = await session.run("Check workspace status");
7
+ console.log(result.text);
8
+ }
9
+
10
+ main().catch((error) => {
11
+ console.error("Personal assistant failed:", error);
12
+ process.exit(1);
13
+ });
@@ -0,0 +1,28 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { assertHostCompositionReadiness, inspectHostComposition } from "@arnilo/prism";
4
+ import { createAppAgent } from "../agent.js";
5
+
6
+ describe("personal assistant template", () => {
7
+ it("creates agent and runs an offline turn", async () => {
8
+ const agent = createAppAgent({ userId: "test-user" });
9
+ const session = agent.createSession({ id: "test-session" });
10
+ const result = await session.run("Hello");
11
+ assert.ok(result.text.includes("Personal Assistant ready"));
12
+ });
13
+
14
+ it("passes personal host composition readiness inspection", () => {
15
+ const agent = createAppAgent({ userId: "test-user" });
16
+ const report = inspectHostComposition({
17
+ profile: "personal",
18
+ agent,
19
+ credentialRefs: ["OPENAI_API_KEY"],
20
+ });
21
+
22
+ assert.equal(report.profile, "personal");
23
+ assert.equal(report.ownership.userId, "test-user");
24
+ assert.equal(report.readiness.ok, true);
25
+ assert.equal(report.storage.durable, false, "in-memory store is non-durable");
26
+ assert.doesNotThrow(() => assertHostCompositionReadiness({ profile: "personal", agent }));
27
+ });
28
+ });
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "strict": true,
7
+ "outDir": "dist",
8
+ "rootDir": "src",
9
+ "declaration": true,
10
+ "skipLibCheck": true,
11
+ "esModuleInterop": true,
12
+ "forceConsistentCasingInFileNames": true
13
+ },
14
+ "include": ["src"]
15
+ }