@framers/agentos 0.13.64 → 0.13.66

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 (73) hide show
  1. package/dist/cognition/emergent/EmergentAgentForge.d.ts.map +1 -1
  2. package/dist/cognition/emergent/EmergentAgentForge.js +5 -4
  3. package/dist/cognition/emergent/EmergentAgentForge.js.map +1 -1
  4. package/dist/cognition/emergent/EmergentCapabilityEngine.d.ts +2 -0
  5. package/dist/cognition/emergent/EmergentCapabilityEngine.d.ts.map +1 -1
  6. package/dist/cognition/emergent/EmergentCapabilityEngine.js +10 -0
  7. package/dist/cognition/emergent/EmergentCapabilityEngine.js.map +1 -1
  8. package/dist/cognition/emergent/ForgeToolMetaTool.d.ts +4 -1
  9. package/dist/cognition/emergent/ForgeToolMetaTool.d.ts.map +1 -1
  10. package/dist/cognition/emergent/ForgeToolMetaTool.js +14 -1
  11. package/dist/cognition/emergent/ForgeToolMetaTool.js.map +1 -1
  12. package/dist/cognition/emergent/SkillExporter.d.ts +44 -3
  13. package/dist/cognition/emergent/SkillExporter.d.ts.map +1 -1
  14. package/dist/cognition/emergent/SkillExporter.js +124 -18
  15. package/dist/cognition/emergent/SkillExporter.js.map +1 -1
  16. package/dist/cognition/emergent/ToolName.d.ts +63 -0
  17. package/dist/cognition/emergent/ToolName.d.ts.map +1 -0
  18. package/dist/cognition/emergent/ToolName.js +79 -0
  19. package/dist/cognition/emergent/ToolName.js.map +1 -0
  20. package/dist/cognition/emergent/index.d.ts +3 -1
  21. package/dist/cognition/emergent/index.d.ts.map +1 -1
  22. package/dist/cognition/emergent/index.js +2 -1
  23. package/dist/cognition/emergent/index.js.map +1 -1
  24. package/dist/cognition/memory/AgentMemory.d.ts +4 -2
  25. package/dist/cognition/memory/AgentMemory.d.ts.map +1 -1
  26. package/dist/cognition/memory/AgentMemory.js +3 -1
  27. package/dist/cognition/memory/AgentMemory.js.map +1 -1
  28. package/dist/cognition/memory/core/types.d.ts +1 -1
  29. package/dist/cognition/memory/core/types.d.ts.map +1 -1
  30. package/dist/cognition/memory/index.d.ts +1 -1
  31. package/dist/cognition/memory/index.d.ts.map +1 -1
  32. package/dist/cognition/memory/index.js.map +1 -1
  33. package/dist/cognition/memory/io/MarkdownExporter.d.ts +53 -9
  34. package/dist/cognition/memory/io/MarkdownExporter.d.ts.map +1 -1
  35. package/dist/cognition/memory/io/MarkdownExporter.js +208 -15
  36. package/dist/cognition/memory/io/MarkdownExporter.js.map +1 -1
  37. package/dist/cognition/memory/io/ObsidianExporter.d.ts +6 -4
  38. package/dist/cognition/memory/io/ObsidianExporter.d.ts.map +1 -1
  39. package/dist/cognition/memory/io/ObsidianExporter.js +5 -3
  40. package/dist/cognition/memory/io/ObsidianExporter.js.map +1 -1
  41. package/dist/cognition/memory/io/facade/Memory.d.ts +15 -3
  42. package/dist/cognition/memory/io/facade/Memory.d.ts.map +1 -1
  43. package/dist/cognition/memory/io/facade/Memory.js +20 -8
  44. package/dist/cognition/memory/io/facade/Memory.js.map +1 -1
  45. package/dist/cognition/memory/io/facade/index.d.ts +1 -1
  46. package/dist/cognition/memory/io/facade/index.d.ts.map +1 -1
  47. package/dist/cognition/memory/io/facade/types.d.ts +41 -0
  48. package/dist/cognition/memory/io/facade/types.d.ts.map +1 -1
  49. package/dist/cognition/memory/io/tools/MemoryAddTool.d.ts +4 -0
  50. package/dist/cognition/memory/io/tools/MemoryAddTool.d.ts.map +1 -1
  51. package/dist/cognition/memory/io/tools/MemoryAddTool.js +18 -4
  52. package/dist/cognition/memory/io/tools/MemoryAddTool.js.map +1 -1
  53. package/dist/cognition/substrate/memory/wiki/WikiCompiler.d.ts +5 -1
  54. package/dist/cognition/substrate/memory/wiki/WikiCompiler.d.ts.map +1 -1
  55. package/dist/cognition/substrate/memory/wiki/WikiCompiler.js +35 -10
  56. package/dist/cognition/substrate/memory/wiki/WikiCompiler.js.map +1 -1
  57. package/dist/cognition/substrate/memory/wiki/WikiMemoryStore.d.ts +23 -4
  58. package/dist/cognition/substrate/memory/wiki/WikiMemoryStore.d.ts.map +1 -1
  59. package/dist/cognition/substrate/memory/wiki/WikiMemoryStore.js +66 -35
  60. package/dist/cognition/substrate/memory/wiki/WikiMemoryStore.js.map +1 -1
  61. package/dist/cognition/substrate/memory/wiki/WikiPageId.d.ts +9 -7
  62. package/dist/cognition/substrate/memory/wiki/WikiPageId.d.ts.map +1 -1
  63. package/dist/cognition/substrate/memory/wiki/WikiPageId.js +20 -32
  64. package/dist/cognition/substrate/memory/wiki/WikiPageId.js.map +1 -1
  65. package/dist/core/utils/linkFreeWrite.d.ts +66 -0
  66. package/dist/core/utils/linkFreeWrite.d.ts.map +1 -0
  67. package/dist/core/utils/linkFreeWrite.js +140 -0
  68. package/dist/core/utils/linkFreeWrite.js.map +1 -0
  69. package/dist/core/utils/pathName.d.ts +66 -0
  70. package/dist/core/utils/pathName.d.ts.map +1 -0
  71. package/dist/core/utils/pathName.js +91 -0
  72. package/dist/core/utils/pathName.js.map +1 -0
  73. package/package.json +1 -1
@@ -0,0 +1,140 @@
1
+ /**
2
+ * @fileoverview Writing below a folder whose contents another process may change: folders are made one name at a
3
+ * time and never through a link, and a file is opened for writing never through a link, never waiting, and only
4
+ * when it is a regular file with one name.
5
+ *
6
+ * The Markdown and Obsidian memory exporters write a file per trace below an export folder, and the skill exporter
7
+ * writes a tool's files below a skills folder. Whoever can write below such a folder could put there a link that
8
+ * leads elsewhere, a second name for a file elsewhere, or a named pipe that holds a writer up, so both write
9
+ * through the functions here. The folder itself is the caller's and may be a link. The checks run as each folder
10
+ * is made and each file opened; Node has no `openat`, so a process that swaps a folder for a link between a check
11
+ * and the write is outside what they stop.
12
+ *
13
+ * @module agentos/core/utils/linkFreeWrite
14
+ */
15
+ import fs from 'node:fs/promises';
16
+ import { constants as fsConstants } from 'node:fs';
17
+ import path from 'node:path';
18
+ /**
19
+ * The flags a file is opened with: for writing, made when missing, and, where the platform has each flag (Windows
20
+ * has neither), never through a symbolic link in the file's own place (`O_NOFOLLOW`) and never waiting
21
+ * (`O_NONBLOCK`). Without `O_NONBLOCK`, an open for writing of a named pipe that no process reads waits for a
22
+ * reader that may never come. The file is not emptied by the open: the caller empties it once the open file shows
23
+ * it is a regular file with no second name.
24
+ */
25
+ const OPEN_FLAGS = fsConstants.O_WRONLY |
26
+ fsConstants.O_CREAT |
27
+ (fsConstants.O_NOFOLLOW !== undefined ? fsConstants.O_NOFOLLOW : 0) |
28
+ (fsConstants.O_NONBLOCK !== undefined ? fsConstants.O_NONBLOCK : 0);
29
+ /** The codes an open with `O_NOFOLLOW` fails with when a symbolic link holds the file's place (EMLINK on FreeBSD). */
30
+ const LINK_OPEN_CODES = new Set(['ELOOP', 'EMLINK']);
31
+ /**
32
+ * The codes an open for writing fails with when something other than a regular file holds the file's place:
33
+ * EISDIR for a folder; ENXIO for a named pipe that no process reads (under `O_NONBLOCK`), a device with no driver,
34
+ * or, on Linux, a socket; EOPNOTSUPP for a socket on macOS.
35
+ */
36
+ const SPECIAL_OPEN_CODES = new Set(['EISDIR', 'ENXIO', 'EOPNOTSUPP']);
37
+ /**
38
+ * Make the folders `relative` names under `root`, one name at a time, and stop at a link. A folder this makes is
39
+ * never a link, so a file written into it stays under `root`.
40
+ *
41
+ * @param root - The folder the others are made in. It may itself be a link.
42
+ * @param relative - The folders' path under `root`.
43
+ * @returns True when every folder is in place and none of them is a link.
44
+ */
45
+ export async function makeFoldersOutsideLinks(root, relative) {
46
+ let dir = root;
47
+ for (const name of relative.split(path.sep).filter((part) => part.length > 0)) {
48
+ dir = path.join(dir, name);
49
+ const entry = await lstatOrNull(dir);
50
+ if (entry) {
51
+ if (entry.isSymbolicLink())
52
+ return false;
53
+ continue;
54
+ }
55
+ try {
56
+ await fs.mkdir(dir);
57
+ }
58
+ catch (err) {
59
+ if (err.code !== 'EEXIST')
60
+ throw err;
61
+ // Something was put there since the look: look again.
62
+ if ((await fs.lstat(dir)).isSymbolicLink())
63
+ return false;
64
+ }
65
+ }
66
+ return true;
67
+ }
68
+ /**
69
+ * Look at a file's place without opening it. A caller that writes several files, all of them or none, looks at
70
+ * every place before it opens any file, so a refusal makes no file. The look does not see a change made after it;
71
+ * {@link openFileOutsideLinks} checks again.
72
+ *
73
+ * @param file - Absolute path of the file.
74
+ * @returns `link` when a symbolic link holds the place or the file there has a second name, `special` when
75
+ * something other than a regular file holds it, or null when the place is free or holds a regular file with one
76
+ * name.
77
+ * @throws Any error the look meets other than a missing file.
78
+ */
79
+ export async function lookOutsideLinks(file) {
80
+ const entry = await lstatOrNull(file);
81
+ if (entry === null)
82
+ return null;
83
+ if (entry.isSymbolicLink())
84
+ return 'link';
85
+ if (!entry.isFile())
86
+ return 'special';
87
+ return entry.nlink > 1 ? 'link' : null;
88
+ }
89
+ /**
90
+ * Open a file for writing, in a folder already made, and check what the open reached. A symbolic link in the
91
+ * file's place is refused before the open, and where the platform has `O_NOFOLLOW` the open refuses one put there
92
+ * since. A folder fails the open, and where the platform has `O_NONBLOCK` so does a named pipe that no process
93
+ * reads, at once. An open file that is not a regular file (a named pipe that a process reads, a device) is refused,
94
+ * and so is a file with a second name (a hard link), which is the same file as that name and may lie outside the
95
+ * folder. Nothing is emptied or written here; a refused file is closed.
96
+ *
97
+ * @param file - Absolute path of the file.
98
+ * @returns The open file and its identity, or the refusal.
99
+ * @throws Any other error the look or the open meets.
100
+ */
101
+ export async function openFileOutsideLinks(file) {
102
+ if ((await lstatOrNull(file))?.isSymbolicLink())
103
+ return 'link';
104
+ const handle = await fs.open(file, OPEN_FLAGS).catch((err) => {
105
+ const code = String(err.code);
106
+ if (LINK_OPEN_CODES.has(code))
107
+ return 'link';
108
+ if (SPECIAL_OPEN_CODES.has(code))
109
+ return 'special';
110
+ throw err;
111
+ });
112
+ if (typeof handle === 'string')
113
+ return handle;
114
+ let handedOver = false;
115
+ try {
116
+ const stat = await handle.stat({ bigint: true });
117
+ if (!stat.isFile())
118
+ return 'special';
119
+ if (stat.nlink > 1n)
120
+ return 'link';
121
+ handedOver = true;
122
+ return { handle, identity: stat.ino === 0n ? null : `${stat.dev}:${stat.ino}` };
123
+ }
124
+ finally {
125
+ if (!handedOver)
126
+ await handle.close();
127
+ }
128
+ }
129
+ /** The entry at `file` itself, a link not followed, or null when there is none. */
130
+ async function lstatOrNull(file) {
131
+ try {
132
+ return await fs.lstat(file);
133
+ }
134
+ catch (err) {
135
+ if (err.code === 'ENOENT')
136
+ return null;
137
+ throw err;
138
+ }
139
+ }
140
+ //# sourceMappingURL=linkFreeWrite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linkFreeWrite.js","sourceRoot":"","sources":["../../../src/core/utils/linkFreeWrite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * @fileoverview The rule for a file or folder name built from data, and the check that a path built from such
3
+ * names lies inside its folder.
4
+ *
5
+ * The memory wiki builds a page's path from its id, the Markdown and Obsidian memory exporters build a trace's
6
+ * path from its scope, type and id, and the skill exporter builds a forged tool's folder from its name. Those
7
+ * values come from files, imports and models, so every name taken from them is checked against one rule here,
8
+ * and every path built from them is checked to lie inside the folder it is written to.
9
+ *
10
+ * @module agentos/core/utils/pathName
11
+ */
12
+ import * as path from 'node:path';
13
+ /**
14
+ * The most bytes, in UTF-8, one name may hold. Linux allows 255 bytes in a name, and Windows usually 255 UTF-16
15
+ * code units; a name never holds more code units than bytes, so 200 fits both and leaves room for the extension a
16
+ * caller adds, such as `.md`.
17
+ */
18
+ export declare const MAX_PATH_NAME_BYTES = 200;
19
+ /**
20
+ * Why a name was refused:
21
+ * - `'empty'`: the name is empty.
22
+ * - `'character'`: it holds a slash, a backslash, a colon, one of `"`, `*`, `<`, `>`, `?` and `|`, or a control
23
+ * character (U+0000 to U+001F, or U+007F), a NUL byte among them. A slash or a backslash separates folders; on
24
+ * Windows a colon names a drive (`C:name`) or a file's stream (`name:stream`), and Windows refuses the other six
25
+ * in a name.
26
+ * - `'dot'`: it starts with a dot, so it is `.`, `..` or a hidden name.
27
+ * - `'edge'`: it starts or ends with a space, or ends with a dot. Windows drops those from a name, so the name
28
+ * would be another's (`notes.` is `notes` there).
29
+ * - `'length'`: it holds more than {@link MAX_PATH_NAME_BYTES} bytes in UTF-8.
30
+ */
31
+ export type PathNameProblem = 'empty' | 'character' | 'dot' | 'edge' | 'length';
32
+ /**
33
+ * A refused value as an error message shows it: a string quoted and escaped, cut to its first 64 characters, or
34
+ * the type of any other value.
35
+ *
36
+ * @param value - The refused value.
37
+ */
38
+ export declare function describeRefusedName(value: unknown): string;
39
+ /**
40
+ * True when the character whose UTF-16 code is `code` may appear neither in a name nor anywhere in a path whose
41
+ * names are joined with `/`: a backslash, a colon, one of `"`, `*`, `<`, `>`, `?` and `|`, or a control character
42
+ * (U+0000 to U+001F, or U+007F).
43
+ */
44
+ export declare function isRefusedPathCharacter(code: number): boolean;
45
+ /**
46
+ * The part of the name rule `name` breaks, or null when `name` may name one file or folder. A name the rule
47
+ * accepts holds no separator, is never `.` or `..`, and names no drive or file stream, so a path built from such
48
+ * names stays under the folder it starts from.
49
+ *
50
+ * @param name - The name to check.
51
+ */
52
+ export declare function pathNameProblem(name: string): PathNameProblem | null;
53
+ /**
54
+ * The path that `relative` names under the folder `root`, resolved, or null when that path is not inside `root`.
55
+ * The paths are compared resolved, with the separator after the folder's own path, so a sibling folder whose name
56
+ * starts with the folder's (`/srv/memory-old` beside `/srv/memory`) is not inside it, and neither is the folder
57
+ * itself. The check is on the path as written: a link inside the folder is not followed.
58
+ *
59
+ * @param root - The folder.
60
+ * @param relative - The parts of the path under `root`, in order, as `path.resolve` takes them.
61
+ * @param paths - The path functions to resolve with: the platform's by default, `path.win32` or `path.posix` to
62
+ * pick one.
63
+ * @returns The absolute path, or null when it is outside `root`.
64
+ */
65
+ export declare function resolveInsideFolder(root: string, relative: readonly string[], paths?: Pick<path.PlatformPath, 'resolve' | 'sep'>): string | null;
66
+ //# sourceMappingURL=pathName.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pathName.d.ts","sourceRoot":"","sources":["../../../src/core/utils/pathName.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,WAAW,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAC;AAmBhF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAK1D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAWpE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,KAAK,GAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,KAAK,CAAQ,GACvD,MAAM,GAAG,IAAI,CAKf"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @fileoverview The rule for a file or folder name built from data, and the check that a path built from such
3
+ * names lies inside its folder.
4
+ *
5
+ * The memory wiki builds a page's path from its id, the Markdown and Obsidian memory exporters build a trace's
6
+ * path from its scope, type and id, and the skill exporter builds a forged tool's folder from its name. Those
7
+ * values come from files, imports and models, so every name taken from them is checked against one rule here,
8
+ * and every path built from them is checked to lie inside the folder it is written to.
9
+ *
10
+ * @module agentos/core/utils/pathName
11
+ */
12
+ import * as path from 'node:path';
13
+ /**
14
+ * The most bytes, in UTF-8, one name may hold. Linux allows 255 bytes in a name, and Windows usually 255 UTF-16
15
+ * code units; a name never holds more code units than bytes, so 200 fits both and leaves room for the extension a
16
+ * caller adds, such as `.md`.
17
+ */
18
+ export const MAX_PATH_NAME_BYTES = 200;
19
+ /** The slash's code: the folder separator everywhere. */
20
+ const SLASH = 0x2f;
21
+ /** The backslash's code: a folder separator on Windows. */
22
+ const BACKSLASH = 0x5c;
23
+ /** The colon's code: on Windows it names a drive (`C:name`) or a file's stream (`name:stream`). */
24
+ const COLON = 0x3a;
25
+ /** The codes of `"`, `*`, `<`, `>`, `?` and `|`, which Windows refuses in a name. */
26
+ const WINDOWS_RESERVED = new Set([0x22, 0x2a, 0x3c, 0x3e, 0x3f, 0x7c]);
27
+ const utf8 = new TextEncoder();
28
+ /** The most characters of a refused name that an error message shows. */
29
+ const SHOWN_NAME_CHARACTERS = 64;
30
+ /**
31
+ * A refused value as an error message shows it: a string quoted and escaped, cut to its first 64 characters, or
32
+ * the type of any other value.
33
+ *
34
+ * @param value - The refused value.
35
+ */
36
+ export function describeRefusedName(value) {
37
+ if (typeof value !== 'string')
38
+ return `of type ${value === null ? 'null' : typeof value}`;
39
+ return JSON.stringify(value.length > SHOWN_NAME_CHARACTERS ? `${value.slice(0, SHOWN_NAME_CHARACTERS)}...` : value);
40
+ }
41
+ /**
42
+ * True when the character whose UTF-16 code is `code` may appear neither in a name nor anywhere in a path whose
43
+ * names are joined with `/`: a backslash, a colon, one of `"`, `*`, `<`, `>`, `?` and `|`, or a control character
44
+ * (U+0000 to U+001F, or U+007F).
45
+ */
46
+ export function isRefusedPathCharacter(code) {
47
+ return code <= 0x1f || code === 0x7f || code === BACKSLASH || code === COLON || WINDOWS_RESERVED.has(code);
48
+ }
49
+ /**
50
+ * The part of the name rule `name` breaks, or null when `name` may name one file or folder. A name the rule
51
+ * accepts holds no separator, is never `.` or `..`, and names no drive or file stream, so a path built from such
52
+ * names stays under the folder it starts from.
53
+ *
54
+ * @param name - The name to check.
55
+ */
56
+ export function pathNameProblem(name) {
57
+ if (name.length === 0)
58
+ return 'empty';
59
+ for (let i = 0; i < name.length; i++) {
60
+ const code = name.charCodeAt(i);
61
+ if (code === SLASH || isRefusedPathCharacter(code))
62
+ return 'character';
63
+ }
64
+ if (name.startsWith('.'))
65
+ return 'dot';
66
+ if (name.startsWith(' ') || name.endsWith(' ') || name.endsWith('.'))
67
+ return 'edge';
68
+ // A string never has more UTF-16 code units than UTF-8 bytes, so a long one is refused before it is encoded.
69
+ if (name.length > MAX_PATH_NAME_BYTES || utf8.encode(name).byteLength > MAX_PATH_NAME_BYTES)
70
+ return 'length';
71
+ return null;
72
+ }
73
+ /**
74
+ * The path that `relative` names under the folder `root`, resolved, or null when that path is not inside `root`.
75
+ * The paths are compared resolved, with the separator after the folder's own path, so a sibling folder whose name
76
+ * starts with the folder's (`/srv/memory-old` beside `/srv/memory`) is not inside it, and neither is the folder
77
+ * itself. The check is on the path as written: a link inside the folder is not followed.
78
+ *
79
+ * @param root - The folder.
80
+ * @param relative - The parts of the path under `root`, in order, as `path.resolve` takes them.
81
+ * @param paths - The path functions to resolve with: the platform's by default, `path.win32` or `path.posix` to
82
+ * pick one.
83
+ * @returns The absolute path, or null when it is outside `root`.
84
+ */
85
+ export function resolveInsideFolder(root, relative, paths = path) {
86
+ const folder = paths.resolve(root);
87
+ const file = paths.resolve(folder, ...relative);
88
+ const inside = folder.endsWith(paths.sep) ? folder : folder + paths.sep;
89
+ return file.startsWith(inside) ? file : null;
90
+ }
91
+ //# sourceMappingURL=pathName.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pathName.js","sourceRoot":"","sources":["../../../src/core/utils/pathName.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@framers/agentos",
3
- "version": "0.13.64",
3
+ "version": "0.13.66",
4
4
  "description": "AgentOS: open-source TypeScript framework for autonomous AI agents. Unified graph orchestration, cognitive memory, runtime tool forging, multi-tier guardrails, voice pipeline, and 11 LLM providers.",
5
5
  "homepage": "https://agentos.sh",
6
6
  "repository": {