@withloops.ai/contracts 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,46 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Every permission an app can ask for. One list for REST, MCP, events and LoopKit (skill §8 "one scope list").
4
+ * Only ever ADD to this list (versioning promise). `consent` is the plain-words line on the install sheet
5
+ * ("<App> can …"), sentence case.
6
+ */
7
+ export declare const SCOPES: {
8
+ readonly 'contacts:read': "See contacts: names, emails, phone numbers and their company";
9
+ readonly 'contacts:write': "Add and change contacts";
10
+ readonly 'companies:read': "See companies";
11
+ readonly 'companies:write': "Add and change companies";
12
+ readonly 'leads:read': "See leads";
13
+ readonly 'leads:write': "Add and change leads";
14
+ readonly 'deals:read': "See deals and the people on them";
15
+ readonly 'deals:write': "Add and change deals";
16
+ readonly 'notes:write': "Write notes on records, marked with the app’s name";
17
+ readonly 'actions:write': "Add Actions for people in your workspace";
18
+ readonly 'loops:read': "Read messages in loops the app is added to";
19
+ readonly 'loops:write': "Post in loops the app is added to, marked with the app’s name";
20
+ readonly 'calls:read': "See calls and their transcripts";
21
+ readonly 'meetings:read': "See meetings and their notes";
22
+ readonly 'webhooks:manage': "Send events from your workspace to the app";
23
+ };
24
+ export type Scope = keyof typeof SCOPES;
25
+ export declare const SCOPE_NAMES: [Scope, ...Scope[]];
26
+ export declare const ScopeSchema: z.ZodEnum<{
27
+ "contacts:read": "contacts:read";
28
+ "contacts:write": "contacts:write";
29
+ "companies:read": "companies:read";
30
+ "companies:write": "companies:write";
31
+ "leads:read": "leads:read";
32
+ "leads:write": "leads:write";
33
+ "deals:read": "deals:read";
34
+ "deals:write": "deals:write";
35
+ "notes:write": "notes:write";
36
+ "actions:write": "actions:write";
37
+ "loops:read": "loops:read";
38
+ "loops:write": "loops:write";
39
+ "calls:read": "calls:read";
40
+ "meetings:read": "meetings:read";
41
+ "webhooks:manage": "webhooks:manage";
42
+ }>;
43
+ /** The consent line for a scope, e.g. on the install sheet. */
44
+ export declare function consentLine(scope: Scope): string;
45
+ /** A `write` scope implies its `read` (asking for contacts:write shows both lines). */
46
+ export declare function expandScopes(scopes: readonly Scope[]): Scope[];
package/dist/scopes.js ADDED
@@ -0,0 +1,40 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Every permission an app can ask for. One list for REST, MCP, events and LoopKit (skill §8 "one scope list").
4
+ * Only ever ADD to this list (versioning promise). `consent` is the plain-words line on the install sheet
5
+ * ("<App> can …"), sentence case.
6
+ */
7
+ export const SCOPES = {
8
+ 'contacts:read': 'See contacts: names, emails, phone numbers and their company',
9
+ 'contacts:write': 'Add and change contacts',
10
+ 'companies:read': 'See companies',
11
+ 'companies:write': 'Add and change companies',
12
+ 'leads:read': 'See leads',
13
+ 'leads:write': 'Add and change leads',
14
+ 'deals:read': 'See deals and the people on them',
15
+ 'deals:write': 'Add and change deals',
16
+ 'notes:write': 'Write notes on records, marked with the app’s name',
17
+ 'actions:write': 'Add Actions for people in your workspace',
18
+ 'loops:read': 'Read messages in loops the app is added to',
19
+ 'loops:write': 'Post in loops the app is added to, marked with the app’s name',
20
+ 'calls:read': 'See calls and their transcripts',
21
+ 'meetings:read': 'See meetings and their notes',
22
+ 'webhooks:manage': 'Send events from your workspace to the app',
23
+ };
24
+ export const SCOPE_NAMES = Object.keys(SCOPES);
25
+ export const ScopeSchema = z.enum(SCOPE_NAMES);
26
+ /** The consent line for a scope, e.g. on the install sheet. */
27
+ export function consentLine(scope) {
28
+ return SCOPES[scope];
29
+ }
30
+ /** A `write` scope implies its `read` (asking for contacts:write shows both lines). */
31
+ export function expandScopes(scopes) {
32
+ const out = new Set(scopes);
33
+ for (const s of scopes) {
34
+ const [res, op] = s.split(':');
35
+ const read = `${res}:read`;
36
+ if (op === 'write' && read in SCOPES)
37
+ out.add(read);
38
+ }
39
+ return SCOPE_NAMES.filter((s) => out.has(s));
40
+ }
package/package.json CHANGED
@@ -1,29 +1,35 @@
1
1
  {
2
2
  "name": "@withloops.ai/contracts",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "The Loops developer platform contracts (zod): app manifest v1, scopes, events, the /v1 API envelope and registry records. Everything else builds on these.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
7
7
  "exports": {
8
- ".": "./src/index.ts"
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
9
12
  },
10
13
  "files": [
14
+ "dist",
11
15
  "src",
12
16
  "examples"
13
17
  ],
14
18
  "engines": {
15
- "node": ">=22.18"
19
+ "node": ">=26"
16
20
  },
17
21
  "scripts": {
18
22
  "test": "node --test \"test/*.test.ts\"",
19
- "typecheck": "tsc --noEmit"
23
+ "typecheck": "tsc --noEmit",
24
+ "build": "tsc -p tsconfig.build.json",
25
+ "prepublishOnly": "npm run build"
20
26
  },
21
27
  "dependencies": {
22
28
  "zod": "^4.3.6"
23
29
  },
24
30
  "devDependencies": {
25
31
  "typescript": "^5.9.3",
26
- "@types/node": "^24.0.0"
32
+ "@types/node": "^26.0.0"
27
33
  },
28
34
  "homepage": "https://withloops.ai",
29
35
  "keywords": [
@@ -31,5 +37,7 @@
31
37
  "withloops",
32
38
  "sdk",
33
39
  "contracts"
34
- ]
40
+ ],
41
+ "main": "./dist/index.js",
42
+ "types": "./dist/index.d.ts"
35
43
  }
package/src/registry.ts CHANGED
@@ -111,6 +111,8 @@ export type Caller = z.infer<typeof Caller>;
111
111
  export interface RegistryRpc {
112
112
  submit(caller: Caller, manifest: unknown): Promise<{ ok: true; version: AppVersionRecord } | { ok: false; errors: string[] }>;
113
113
  listMarketplace(caller: Caller): Promise<Listing[]>;
114
+ /** Apps owned by the caller's workspace (`GET /v1/developer/apps`). Added in 0.2.0. */
115
+ listApps(caller: Caller): Promise<AppRecord[]>;
114
116
  getApp(caller: Caller, appId: string): Promise<{ app: AppRecord; versions: AppVersionRecord[] } | null>;
115
117
  install(caller: Caller, appId: string, grantedScopes: string[]): Promise<{ ok: true; install: InstallRecord } | { ok: false; error: string }>;
116
118
  uninstall(caller: Caller, installId: string): Promise<{ ok: boolean }>;