epismo 0.1.2 → 0.1.4

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
@@ -4,6 +4,18 @@ GitHub made code reusable. Hugging Face made models reusable. Epismo makes human
4
4
 
5
5
  Capture how you got your best results — not just the output — and share them as executable workflows that agents and humans can discover, adapt, and run across projects.
6
6
 
7
+ ## CLI Contract
8
+
9
+ Epismo CLI is designed for agents first.
10
+
11
+ - Non-interactive runs default to machine-readable JSON.
12
+ - Interactive TTY runs also keep success output machine-readable on `stdout`.
13
+ - `stderr` is used for prompts, browser-login guidance, and error output.
14
+ - Exit code `0` indicates success. Any non-zero exit code indicates failure.
15
+
16
+ In interactive sessions, the CLI may prompt on `stderr`.
17
+ In non-interactive environments, commands that need prompts fail fast instead of waiting for input.
18
+
7
19
  ## Install
8
20
 
9
21
  ```bash
@@ -19,38 +31,43 @@ npx epismo <command>
19
31
  ## Authentication
20
32
 
21
33
  ```bash
22
- epismo login # OTP (prompts for email + code)
23
- epismo login --email you@example.com --pin 123456 # inline values
24
- epismo login --browser # OAuth via browser
25
- epismo logout # clear local credentials
34
+ epismo login # OTP (prompts for email + code)
35
+ epismo login --email you@example.com --otp 123456 # inline values
36
+ epismo login --browser # OAuth via browser
37
+ epismo logout # clear local credentials
38
+ EPISMO_TOKEN=<access-token> epismo whoami # preferred for scripts
26
39
  ```
27
40
 
41
+ If `EPISMO_TOKEN` is set, the CLI uses it instead of stored credentials.
42
+
43
+ When `EPISMO_TOKEN` is active, the saved default workspace is ignored unless you pass `--workspace-id`.
44
+
28
45
  ## Commands
29
46
 
30
47
  ### `epismo whoami`
31
48
 
32
- Show the current user and accessible workspaces.
49
+ Show the current user, effective workspace context, and accessible workspaces.
33
50
 
34
51
  ### `epismo workspace`
35
52
 
36
53
  ```bash
37
- epismo workspace list # list accessible workspaces
38
- epismo workspace current # show saved default
39
- epismo workspace use <workspace-id> # set default workspace
40
- epismo workspace clear # clear default workspace
54
+ epismo workspace list # list accessible workspaces
55
+ epismo workspace current # show saved default from local config only
56
+ epismo workspace use --workspace-id <workspace-id> # set default workspace
57
+ epismo workspace clear # clear default workspace
41
58
  ```
42
59
 
43
60
  ### `epismo track`
44
61
 
45
- Manage tasks, notes, and goals.
62
+ Manage tasks and goals.
46
63
 
47
64
  ```bash
48
65
  epismo track upsert --type task --title "Fix bug" --content "Details..."
49
66
  epismo track upsert --input @task.json
50
- epismo track get --type task --id <id>
67
+ epismo track get --id <id>
51
68
  epismo track search --type task --query "bug" --filter '{"status":["todo"]}'
52
- epismo track search --type task --query "bug" --view summary
53
- epismo track delete --type task --id <id>
69
+ epismo track search --type task --query "bug" --view brief
70
+ epismo track delete --id <id>
54
71
  ```
55
72
 
56
73
  ### `epismo asset`
@@ -59,12 +76,26 @@ Manage workflows and other assets.
59
76
 
60
77
  ```bash
61
78
  epismo asset upsert --type workflow --title "My workflow" --input @workflow.json
62
- epismo asset get --type workflow --id <id>
79
+ epismo asset get --id <id>
80
+ epismo asset get --alias myproject
81
+ epismo asset get --alias @epismo/myproject
63
82
  epismo asset search --type workflow --query "onboarding" --filter '{"visibility":["public"]}'
64
- epismo asset search --type workflow --query "onboarding" --view summary
65
- epismo asset like --type workflow --id <id> --liked true
66
- epismo asset import --project-id <project-id> --asset-ids <id1>,<id2>
67
- epismo asset delete --type workflow --id <id>
83
+ epismo asset search --type workflow --query "onboarding" --view brief
84
+ epismo asset like --id <id> --liked
85
+ epismo asset like --id <id> --no-liked
86
+ epismo asset delete --id <id> # also removes your aliases for that asset
87
+ ```
88
+
89
+ ### `epismo alias`
90
+
91
+ Manage aliases as a top-level resource.
92
+
93
+ ```bash
94
+ epismo alias upsert --type workflow --id <id> --alias myproject
95
+ epismo alias get --alias myproject
96
+ epismo alias get --alias @epismo/myproject # another user's alias
97
+ epismo alias list
98
+ epismo alias delete --alias myproject
68
99
  ```
69
100
 
70
101
  ### `epismo credit`
@@ -72,6 +103,7 @@ epismo asset delete --type workflow --id <id>
72
103
  ```bash
73
104
  epismo credit balance
74
105
  epismo credit balance --workspace-id <workspace-id>
106
+ epismo credit checkout --allocations '[{"userId":"<user-id>","quantity":10}]'
75
107
  ```
76
108
 
77
109
  ## Skills
@@ -82,9 +114,11 @@ Browse skills: https://github.com/epismoai/skills
82
114
 
83
115
  ## Workspace Selection
84
116
 
85
- - `epismo workspace use <workspace-id>` saves the default for all commands.
117
+ - `epismo workspace use --workspace-id <workspace-id>` saves the default for all commands.
86
118
  - `--workspace-id <id>` overrides the default for a single command.
87
119
  - If neither is set, the CLI operates in personal context.
120
+ - `epismo workspace current` reads only local config and does not require network access.
121
+ - When `EPISMO_TOKEN` is active, saved default workspace selection is ignored unless `--workspace-id` is provided.
88
122
 
89
123
  ## Input
90
124
 
@@ -92,7 +126,28 @@ Browse skills: https://github.com/epismoai/skills
92
126
  - `--input @path/to/file.json` — load from file
93
127
  - `--input -` — read from stdin
94
128
  - Explicit flags override fields from `--input`
129
+ - Enum-like flags are validated in the CLI before the request is sent.
95
130
 
96
131
  ## Output
97
132
 
98
- All commands output JSON by default. Pass `--json` to force JSON when a human-readable summary is also available.
133
+ - Successful command output is JSON on `stdout`.
134
+ - Errors and warnings are written to `stderr` as JSON.
135
+ - Prompts and browser-login guidance are also written to `stderr`.
136
+
137
+ **Error shape** (`stderr`, exit code ≠ 0):
138
+
139
+ ```json
140
+ { "error": { "code": "NOT_FOUND", "message": "...", "retryable": false, "hint": "..." } }
141
+ ```
142
+
143
+ **Warning shape** (`stderr`, exit code 0):
144
+
145
+ ```json
146
+ { "warning": { "code": "UPDATE_AVAILABLE", "message": "..." } }
147
+ ```
148
+
149
+ ## Update Checks
150
+
151
+ Automatic update checks are enabled by default (once per day, shown only in interactive TTY sessions).
152
+
153
+ - Set `EPISMO_UPDATE_CHECK=0` to disable the background npm version check.
@@ -0,0 +1,31 @@
1
+ import { requestJson, withWorkspaceQuery } from "./api.js";
2
+ import { resolveApiUrl } from "./config.js";
3
+ import { readRequiredString, toObjectInput } from "./input.js";
4
+ export async function upsertAlias(context, input) {
5
+ return requestJson(resolveApiUrl(), withWorkspaceQuery("/v1/aliases", context.workspaceId), {
6
+ method: "PUT",
7
+ authToken: context.auth.accessToken,
8
+ body: toObjectInput(input)
9
+ });
10
+ }
11
+ export async function getAlias(context, input) {
12
+ const alias = readRequiredString(input, "alias", "Pass --alias <alias>.");
13
+ const params = new URLSearchParams();
14
+ params.set("alias", alias);
15
+ return requestJson(resolveApiUrl(), withWorkspaceQuery(`/v1/aliases?${params.toString()}`, context.workspaceId), {
16
+ authToken: context.auth.accessToken
17
+ });
18
+ }
19
+ export async function listAliases(context) {
20
+ return requestJson(resolveApiUrl(), withWorkspaceQuery("/v1/aliases", context.workspaceId), {
21
+ authToken: context.auth.accessToken
22
+ });
23
+ }
24
+ export async function deleteAlias(context, input) {
25
+ const alias = readRequiredString(input, "alias", "Pass --alias <alias>.");
26
+ return requestJson(resolveApiUrl(), withWorkspaceQuery(`/v1/aliases/${encodeURIComponent(alias)}`, context.workspaceId), {
27
+ method: "DELETE",
28
+ authToken: context.auth.accessToken
29
+ });
30
+ }
31
+ //# sourceMappingURL=aliases.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aliases.js","sourceRoot":"","sources":["../src/aliases.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/D,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,OAAyB,EACzB,KAAc;IAEd,OAAO,WAAW,CACjB,aAAa,EAAE,EACf,kBAAkB,CAAC,aAAa,EAAE,OAAO,CAAC,WAAW,CAAC,EACtD;QACC,MAAM,EAAE,KAAK;QACb,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW;QACnC,IAAI,EAAE,aAAa,CAAC,KAAK,CAAC;KAC1B,CACD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC7B,OAAyB,EACzB,KAAc;IAEd,MAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,uBAAuB,CAAC,CAAC;IAC1E,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC3B,OAAO,WAAW,CACjB,aAAa,EAAE,EACf,kBAAkB,CAAC,eAAe,MAAM,CAAC,QAAQ,EAAE,EAAE,EAAE,OAAO,CAAC,WAAW,CAAC,EAC3E;QACC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW;KACnC,CACD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAyB;IAC1D,OAAO,WAAW,CACjB,aAAa,EAAE,EACf,kBAAkB,CAAC,aAAa,EAAE,OAAO,CAAC,WAAW,CAAC,EACtD;QACC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW;KACnC,CACD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,OAAyB,EACzB,KAAc;IAEd,MAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,uBAAuB,CAAC,CAAC;IAC1E,OAAO,WAAW,CACjB,aAAa,EAAE,EACf,kBAAkB,CAAC,eAAe,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,WAAW,CAAC,EACnF;QACC,MAAM,EAAE,QAAQ;QAChB,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW;KACnC,CACD,CAAC;AACH,CAAC"}
package/dist/api.js CHANGED
@@ -1,3 +1,12 @@
1
+ import { CliError } from "./errors.js";
2
+ export function withWorkspaceQuery(pathname, workspaceId) {
3
+ if (!workspaceId?.trim()) {
4
+ return pathname;
5
+ }
6
+ const params = new URLSearchParams({ workspaceId: workspaceId.trim() });
7
+ const separator = pathname.includes("?") ? "&" : "?";
8
+ return `${pathname}${separator}${params.toString()}`;
9
+ }
1
10
  export async function requestJson(apiUrl, pathname, options = {}) {
2
11
  const headers = {};
3
12
  if (options.body !== undefined) {
@@ -6,11 +15,35 @@ export async function requestJson(apiUrl, pathname, options = {}) {
6
15
  if (options.authToken) {
7
16
  headers.authorization = `Bearer ${options.authToken}`;
8
17
  }
9
- const response = await fetch(`${apiUrl}${pathname}`, {
10
- method: options.method ?? "GET",
11
- headers,
12
- body: options.body !== undefined ? JSON.stringify(options.body) : undefined
13
- });
18
+ const controller = new AbortController();
19
+ const timeoutId = setTimeout(() => controller.abort(), 30_000);
20
+ let response;
21
+ try {
22
+ response = await fetch(`${apiUrl}${pathname}`, {
23
+ method: options.method ?? "GET",
24
+ headers,
25
+ body: options.body !== undefined ? JSON.stringify(options.body) : undefined,
26
+ signal: controller.signal
27
+ });
28
+ }
29
+ catch (error) {
30
+ if (error instanceof Error && error.name === "AbortError") {
31
+ throw new CliError({
32
+ code: "REQUEST_TIMEOUT",
33
+ message: "Request timed out.",
34
+ retryable: true
35
+ });
36
+ }
37
+ const message = error instanceof Error ? error.message : String(error);
38
+ throw new CliError({
39
+ code: "NETWORK_ERROR",
40
+ message,
41
+ retryable: true
42
+ });
43
+ }
44
+ finally {
45
+ clearTimeout(timeoutId);
46
+ }
14
47
  const text = await response.text();
15
48
  let parsed = {};
16
49
  if (text) {
@@ -29,9 +62,39 @@ export async function requestJson(apiUrl, pathname, options = {}) {
29
62
  ? payload.error
30
63
  : typeof payload.error_description === "string"
31
64
  ? payload.error_description
32
- : `HTTP ${response.status}`;
33
- throw new Error(message);
65
+ : typeof payload.message === "string"
66
+ ? payload.message
67
+ : `HTTP ${response.status}`;
68
+ throw new CliError({
69
+ code: mapHttpErrorCode(response.status),
70
+ message,
71
+ retryable: response.status >= 500 || response.status === 429,
72
+ details: {
73
+ status: response.status,
74
+ pathname
75
+ }
76
+ });
34
77
  }
35
78
  return parsed;
36
79
  }
80
+ function mapHttpErrorCode(status) {
81
+ switch (status) {
82
+ case 400:
83
+ return "BAD_REQUEST";
84
+ case 401:
85
+ return "UNAUTHORIZED";
86
+ case 403:
87
+ return "FORBIDDEN";
88
+ case 404:
89
+ return "NOT_FOUND";
90
+ case 409:
91
+ return "CONFLICT";
92
+ case 422:
93
+ return "UNPROCESSABLE_ENTITY";
94
+ case 429:
95
+ return "RATE_LIMITED";
96
+ default:
97
+ return status >= 500 ? "SERVER_ERROR" : "HTTP_ERROR";
98
+ }
99
+ }
37
100
  //# sourceMappingURL=api.js.map
package/dist/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,MAAc,EACd,QAAgB,EAChB,UAA8B,EAAE;IAEhC,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;IAC9C,CAAC;IACD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACvB,OAAO,CAAC,aAAa,GAAG,UAAU,OAAO,CAAC,SAAS,EAAE,CAAC;IACvD,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,GAAG,QAAQ,EAAE,EAAE;QACpD,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;QAC/B,OAAO;QACP,IAAI,EAAE,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KAC3E,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,IAAI,MAAM,GAAY,EAAE,CAAC;IACzB,IAAI,IAAI,EAAE,CAAC;QACV,IAAI,CAAC;YACJ,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACR,MAAM,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAC1B,CAAC;IACF,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QAClB,MAAM,OAAO,GACZ,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAC7D,CAAC,CAAE,MAAkC;YACrC,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,OAAO,GACZ,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ;YAChC,CAAC,CAAC,OAAO,CAAC,KAAK;YACf,CAAC,CAAC,OAAO,OAAO,CAAC,iBAAiB,KAAK,QAAQ;gBAC9C,CAAC,CAAC,OAAO,CAAC,iBAAiB;gBAC3B,CAAC,CAAC,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,MAAmB,CAAC;AAC5B,CAAC"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
package/dist/assets.js CHANGED
@@ -1,83 +1,67 @@
1
- import { requestJson } from "./api.js";
1
+ import { requestJson, withWorkspaceQuery } from "./api.js";
2
2
  import { resolveApiUrl } from "./config.js";
3
- function withWorkspaceQuery(pathname, workspaceId) {
4
- if (!workspaceId?.trim()) {
5
- return pathname;
6
- }
7
- const params = new URLSearchParams({ workspaceId: workspaceId.trim() });
8
- return `${pathname}?${params.toString()}`;
9
- }
10
- function readRequiredId(input) {
11
- if (!input || typeof input !== "object") {
12
- throw new Error("id is required.");
13
- }
14
- const id = input.id;
15
- if (typeof id !== "string" || !id.trim()) {
16
- throw new Error("id is required.");
17
- }
18
- return id.trim();
19
- }
20
- function readRequiredType(input) {
21
- if (!input || typeof input !== "object") {
22
- throw new Error("type is required.");
23
- }
24
- const type = input.type;
25
- if (typeof type !== "string" || !type.trim()) {
26
- throw new Error("type is required.");
27
- }
28
- return type.trim();
29
- }
3
+ import { CliError } from "./errors.js";
4
+ import { readAssetReference, readRequiredId, toObjectInput } from "./input.js";
30
5
  export async function upsertAsset(context, input) {
31
- return requestJson(resolveApiUrl(), "/v1/assets", {
6
+ return requestJson(resolveApiUrl(), withWorkspaceQuery("/v1/assets", context.workspaceId), {
32
7
  method: "PUT",
33
8
  authToken: context.auth.accessToken,
34
- body: {
35
- ...(input && typeof input === "object" ? input : {}),
36
- ...(context.workspaceId ? { workspaceId: context.workspaceId } : {})
37
- }
9
+ body: toObjectInput(input)
38
10
  });
39
11
  }
40
- export async function getAsset(context, input) {
41
- const type = readRequiredType(input);
42
- const id = readRequiredId(input);
43
- return requestJson(resolveApiUrl(), withWorkspaceQuery(`/v1/assets/${encodeURIComponent(type)}/${encodeURIComponent(id)}`, context.workspaceId), {
12
+ export async function getAsset(context, input, blockId) {
13
+ const { id, alias } = readAssetReference(input);
14
+ const requestPath = id !== undefined
15
+ ? withWorkspaceQuery(`/v1/assets/${encodeURIComponent(id)}`, context.workspaceId)
16
+ : withWorkspaceQuery(`/v1/assets?alias=${encodeURIComponent(alias ?? "")}`, context.workspaceId);
17
+ const response = await requestJson(resolveApiUrl(), requestPath, {
44
18
  authToken: context.auth.accessToken
45
19
  });
20
+ const asset = response.asset && typeof response.asset === "object" && !Array.isArray(response.asset)
21
+ ? response.asset
22
+ : response;
23
+ if (blockId !== undefined) {
24
+ const blocks = asset["blocks"];
25
+ if (!Array.isArray(blocks)) {
26
+ throw new CliError({
27
+ code: "INVALID_INPUT",
28
+ message: "Asset does not contain context blocks (--block-id requires type=context)."
29
+ });
30
+ }
31
+ const block = blocks.find((n) => typeof n === "object" &&
32
+ n !== null &&
33
+ n["id"] === blockId);
34
+ if (block === undefined) {
35
+ throw new CliError({
36
+ code: "NOT_FOUND",
37
+ message: `Context block '${blockId}' not found in context asset '${id ?? alias}'.`
38
+ });
39
+ }
40
+ return block;
41
+ }
42
+ return asset;
46
43
  }
47
44
  export async function searchAssets(context, input) {
48
45
  return requestJson(resolveApiUrl(), withWorkspaceQuery("/v1/assets/search", context.workspaceId), {
49
46
  method: "POST",
50
47
  authToken: context.auth.accessToken,
51
- body: {
52
- ...(input && typeof input === "object" ? input : {}),
53
- ...(context.workspaceId ? { workspaceId: context.workspaceId } : {})
54
- }
48
+ body: toObjectInput(input)
55
49
  });
56
50
  }
57
51
  export async function likeAsset(context, input) {
52
+ const id = readRequiredId(input);
58
53
  return requestJson(resolveApiUrl(), withWorkspaceQuery("/v1/assets/like", context.workspaceId), {
59
54
  method: "POST",
60
55
  authToken: context.auth.accessToken,
61
56
  body: {
62
- ...(input && typeof input === "object" ? input : {}),
63
- ...(context.workspaceId ? { workspaceId: context.workspaceId } : {})
64
- }
65
- });
66
- }
67
- export async function importAssets(context, input) {
68
- return requestJson(resolveApiUrl(), withWorkspaceQuery("/v1/assets/import", context.workspaceId), {
69
- method: "POST",
70
- authToken: context.auth.accessToken,
71
- body: {
72
- ...(input && typeof input === "object" ? input : {}),
73
- ...(context.workspaceId ? { workspaceId: context.workspaceId } : {})
57
+ ...toObjectInput(input),
58
+ id
74
59
  }
75
60
  });
76
61
  }
77
62
  export async function deleteAsset(context, input) {
78
- const type = readRequiredType(input);
79
63
  const id = readRequiredId(input);
80
- return requestJson(resolveApiUrl(), withWorkspaceQuery(`/v1/assets/${encodeURIComponent(type)}/${encodeURIComponent(id)}`, context.workspaceId), {
64
+ return requestJson(resolveApiUrl(), withWorkspaceQuery(`/v1/assets/${encodeURIComponent(id)}`, context.workspaceId), {
81
65
  method: "DELETE",
82
66
  authToken: context.auth.accessToken
83
67
  });
@@ -1 +1 @@
1
- {"version":3,"file":"assets.js","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"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"}