@letta-ai/letta-agent-sdk 0.8.0 → 0.8.2

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 (51) hide show
  1. package/README.md +23 -0
  2. package/dist/agent-creation.d.ts +2 -1
  3. package/dist/agent-creation.d.ts.map +1 -1
  4. package/dist/app-server-session.d.ts.map +1 -1
  5. package/dist/client-base.d.ts +12 -0
  6. package/dist/client-base.d.ts.map +1 -1
  7. package/dist/client-entry.d.ts +1 -0
  8. package/dist/client-entry.d.ts.map +1 -1
  9. package/dist/client-entry.js +509 -2527
  10. package/dist/client-entry.js.map +14 -12
  11. package/dist/client.d.ts +4 -0
  12. package/dist/client.d.ts.map +1 -1
  13. package/dist/cloud-session.d.ts +4 -1
  14. package/dist/cloud-session.d.ts.map +1 -1
  15. package/dist/index.d.ts +5 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +795 -2645
  18. package/dist/index.js.map +18 -15
  19. package/dist/query-types.d.ts +25 -0
  20. package/dist/query-types.d.ts.map +1 -0
  21. package/dist/query.d.ts +7 -0
  22. package/dist/query.d.ts.map +1 -0
  23. package/dist/remote-session-protocol.d.ts +11 -1
  24. package/dist/remote-session-protocol.d.ts.map +1 -1
  25. package/dist/remote-turn-coordinator.d.ts.map +1 -1
  26. package/dist/repository-types.d.ts +89 -0
  27. package/dist/repository-types.d.ts.map +1 -0
  28. package/dist/skill-loading.d.ts +84 -0
  29. package/dist/skill-loading.d.ts.map +1 -0
  30. package/dist/skill-node.d.ts +28 -0
  31. package/dist/skill-node.d.ts.map +1 -0
  32. package/dist/types.d.ts +17 -84
  33. package/dist/types.d.ts.map +1 -1
  34. package/package.json +2 -2
  35. package/src/agent-creation.ts +37 -1
  36. package/src/app-server-session.ts +35 -2
  37. package/src/client-base.ts +138 -1
  38. package/src/client-entry.ts +1 -0
  39. package/src/client.ts +39 -0
  40. package/src/cloud-session.ts +84 -16
  41. package/src/index.ts +16 -0
  42. package/src/local-app-server.ts +1 -1
  43. package/src/query-types.ts +40 -0
  44. package/src/query.ts +43 -0
  45. package/src/remote-client-session-core.ts +1 -1
  46. package/src/remote-session-protocol.ts +12 -1
  47. package/src/remote-turn-coordinator.ts +5 -1
  48. package/src/repository-types.ts +105 -0
  49. package/src/skill-loading.ts +194 -0
  50. package/src/skill-node.ts +139 -0
  51. package/src/types.ts +42 -100
@@ -614,12 +614,16 @@ export class RemoteTurnCoordinator {
614
614
  const errorCode = approvalConflict
615
615
  ? "approval_conflict"
616
616
  : (turn.errorCode ?? toSdkErrorCode(stopReason));
617
+ const publicError =
618
+ errorCode && errorCode !== "error"
619
+ ? errorCode
620
+ : (turn.detail ?? stopReason ?? "error");
617
621
 
618
622
  return {
619
623
  type: "result",
620
624
  success,
621
625
  result: success ? tracker?.assistantText || undefined : undefined,
622
- error: success ? undefined : (errorCode ?? stopReason ?? "error"),
626
+ error: success ? undefined : publicError,
623
627
  errorCode: success ? undefined : (errorCode ?? "error"),
624
628
  approvalConflict: approvalConflict || undefined,
625
629
  recoverable: approvalConflict
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Letta-hosted repository API types, used by RepositoriesClient and
3
+ * AgentRepositoriesClient. Kept beside their implementation
4
+ * (repositories.ts) and re-exported from types.ts.
5
+ */
6
+
7
+ export interface Repository {
8
+ id: string;
9
+ name: string;
10
+ createdAt: string;
11
+ updatedAt: string;
12
+ }
13
+
14
+ export interface CreateRepositoryParams {
15
+ name: string;
16
+ }
17
+
18
+ export interface ListRepositoriesParams {
19
+ limit?: number;
20
+ offset?: number;
21
+ }
22
+
23
+ export interface ListRepositoriesResult {
24
+ repositories: Repository[];
25
+ hasNextPage: boolean;
26
+ }
27
+
28
+ export interface RepositoryResource {
29
+ type: "repository";
30
+ repositoryId: string;
31
+ /**
32
+ * Whether to trigger a system-prompt recompile after attaching (and after
33
+ * detaching on cleanup) so the session's conversation does not retain
34
+ * stale repository projections. Defaults to `true`.
35
+ */
36
+ recompile?: boolean;
37
+ }
38
+
39
+ export interface RepositoryFileEntry {
40
+ path: string;
41
+ type: "file" | "directory";
42
+ }
43
+
44
+ export interface ListRepositoryFilesParams {
45
+ pathPrefix?: string;
46
+ depth?: number;
47
+ ref?: string;
48
+ }
49
+
50
+ export interface ListRepositoryFilesResult {
51
+ files: RepositoryFileEntry[];
52
+ ref: string;
53
+ }
54
+
55
+ export interface CreateRepositoryFileParams {
56
+ path: string;
57
+ content: string;
58
+ }
59
+
60
+ export interface RepositoryFile {
61
+ path: string;
62
+ content: string;
63
+ contentSha256: string;
64
+ ref?: string;
65
+ }
66
+
67
+ export interface UpdateRepositoryFileParams {
68
+ path: string;
69
+ content?: string;
70
+ newPath?: string;
71
+ precondition?: {
72
+ contentSha256: string;
73
+ };
74
+ }
75
+
76
+ export interface RepositoryFileMutationResult {
77
+ path: string;
78
+ contentSha256: string;
79
+ commitSha: string;
80
+ }
81
+
82
+ export interface DeleteRepositoryFileParams {
83
+ path: string;
84
+ }
85
+
86
+ export interface DeleteRepositoryFileResult {
87
+ success: boolean;
88
+ commitSha: string;
89
+ }
90
+
91
+ export interface RepositoryVersion {
92
+ sha: string;
93
+ message: string;
94
+ timestamp: string;
95
+ author_name: string | null;
96
+ }
97
+
98
+ export interface ListRepositoryVersionsParams {
99
+ path?: string;
100
+ limit?: number;
101
+ }
102
+
103
+ export interface GetRepositoryVersionParams {
104
+ path: string;
105
+ }
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Skill seeding for createAgent({ skills }) — portable core.
3
+ *
4
+ * A skill's canonical shape is a directory: `SKILL.md` plus optional support
5
+ * files (scripts/, references/, ...). Callers pass either a path to such a
6
+ * directory or an inline {@link AgentSkill} object.
7
+ *
8
+ * The platform stores `skills/{name}/SKILL.md` as a memory block labeled
9
+ * `skills/{name}` (see letta-cloud `blockMarkdownPath.ts` /
10
+ * `path_mapping.py`), so SKILL.md instructions ride the create-agent request
11
+ * as a memory block. Support files have no block representation; they are
12
+ * pushed to the agent's memory git repo after creation.
13
+ *
14
+ * This module is part of the portable client graph and must stay free of
15
+ * Node imports. Directory loading and the git push live in `skill-node.ts`,
16
+ * behind the package root, and are injected by the Node client.
17
+ */
18
+
19
+ /**
20
+ * A skill to seed into a new agent's memory filesystem at creation.
21
+ *
22
+ * The instructions become `skills/{name}/SKILL.md` in the agent's memory
23
+ * repo (stored as the memory block labeled `skills/{name}`), so the agent
24
+ * owns and can edit the skill like any other memory. Support `files` land
25
+ * beside it (`skills/{name}/{path}`); they require the Cloud backend from
26
+ * Node.
27
+ */
28
+ export interface AgentSkill {
29
+ /** Directory name: lowercase letters, digits, ".", "_", "-". */
30
+ name: string;
31
+ /**
32
+ * Trigger text: when the agent should load this skill. Rendered as the
33
+ * SKILL.md frontmatter description and always visible to the agent.
34
+ */
35
+ description: string;
36
+ /** SKILL.md body (markdown, without frontmatter). */
37
+ instructions: string;
38
+ /**
39
+ * Optional support files, keyed by path relative to the skill directory
40
+ * (e.g. "scripts/convert.sh"). Cloud backend from Node only.
41
+ */
42
+ files?: Record<string, Uint8Array>;
43
+ }
44
+
45
+ /**
46
+ * Skill item for createAgent(): a path to a skill directory containing
47
+ * SKILL.md (Node runtimes only), or an inline {@link AgentSkill}.
48
+ */
49
+ export type SkillItem = string | AgentSkill;
50
+
51
+ /** Loads a skill directory from disk. Node-only; see skill-node.ts. */
52
+ export type SkillDirectoryLoader = (dirPath: string) => Promise<AgentSkill>;
53
+
54
+ /** Pushes skill support files to an agent's memory git repo. Node-only. */
55
+ export type SkillFilesPusher = (
56
+ target: { apiBaseUrl: string; apiKey: string; agentId: string },
57
+ skills: AgentSkill[],
58
+ ) => Promise<void>;
59
+
60
+ /** Node-only skill capabilities injected by the package-root client. */
61
+ export interface SkillNodeSupport {
62
+ loadSkillDirectory: SkillDirectoryLoader;
63
+ pushSkillSupportFiles: SkillFilesPusher;
64
+ }
65
+
66
+ /** Skill directory names: lowercase, digits, hyphens (letta-code convention). */
67
+ const SKILL_NAME_RE = /^[a-z0-9][a-z0-9._-]*$/;
68
+
69
+ export function assertValidSkillName(name: string): void {
70
+ if (!SKILL_NAME_RE.test(name)) {
71
+ throw new Error(
72
+ `Invalid skill name "${name}". Skill names are directory names: ` +
73
+ `lowercase letters, digits, ".", "_", "-" (e.g. "generating-voice-memos").`,
74
+ );
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Minimal YAML frontmatter reader for SKILL.md: extracts `name` and
80
+ * `description` (plain, quoted, or `>`/`>-` folded scalars) and returns the
81
+ * body without the frontmatter fence. Anything unparsable is left in place.
82
+ */
83
+ export function parseSkillMarkdown(content: string): {
84
+ name?: string;
85
+ description?: string;
86
+ body: string;
87
+ } {
88
+ if (!content.startsWith("---\n") && !content.startsWith("---\r\n")) {
89
+ return { body: content };
90
+ }
91
+ const fence = /\r?\n---[ \t]*(\r?\n|$)/.exec(content.slice(3));
92
+ if (!fence) return { body: content };
93
+ const yamlStart = content.startsWith("---\r\n") ? 5 : 4;
94
+ const yamlEnd = 3 + fence.index;
95
+ const yamlText = content.slice(yamlStart, yamlEnd);
96
+ const body = content.slice(yamlEnd + fence[0].length);
97
+
98
+ const fields: Record<string, string> = {};
99
+ const lines = yamlText.split(/\r?\n/);
100
+ for (let i = 0; i < lines.length; i++) {
101
+ const line = lines[i];
102
+ if (!line || /^\s/.test(line)) continue;
103
+ const colon = line.indexOf(":");
104
+ if (colon <= 0) continue;
105
+ const key = line.slice(0, colon).trim();
106
+ let value = line.slice(colon + 1).trim();
107
+ if (value === ">" || value === ">-" || value === "|" || value === "|-") {
108
+ const folded: string[] = [];
109
+ let next = lines[i + 1];
110
+ while (next !== undefined && (/^\s/.test(next) || next === "")) {
111
+ i++;
112
+ folded.push(next.trim());
113
+ next = lines[i + 1];
114
+ }
115
+ value = folded.filter((part) => part.length > 0).join(" ");
116
+ } else if (
117
+ (value.startsWith('"') && value.endsWith('"') && value.length >= 2) ||
118
+ (value.startsWith("'") && value.endsWith("'") && value.length >= 2)
119
+ ) {
120
+ value = value.slice(1, -1);
121
+ }
122
+ fields[key] = value;
123
+ }
124
+
125
+ return { name: fields["name"], description: fields["description"], body };
126
+ }
127
+
128
+ /**
129
+ * Resolve every skill item to an AgentSkill. Directory paths need the
130
+ * injected Node loader; without one (portable clients) they are rejected.
131
+ */
132
+ export async function resolveSkillItems(
133
+ items: SkillItem[] | undefined,
134
+ loadDirectory?: SkillDirectoryLoader,
135
+ ): Promise<AgentSkill[]> {
136
+ if (!items || items.length === 0) return [];
137
+ const resolved: AgentSkill[] = [];
138
+ for (const item of items) {
139
+ if (typeof item === "string") {
140
+ if (!loadDirectory) {
141
+ throw new Error(
142
+ `Skill directory paths ("${item}") require a Node.js runtime. ` +
143
+ "Pass an inline skill ({ name, description, instructions }) instead.",
144
+ );
145
+ }
146
+ resolved.push(await loadDirectory(item));
147
+ } else {
148
+ assertValidSkillName(item.name);
149
+ if (!item.instructions || item.instructions.trim().length === 0) {
150
+ throw new Error(`Skill "${item.name}" has empty instructions.`);
151
+ }
152
+ if (!item.description || item.description.trim().length === 0) {
153
+ throw new Error(
154
+ `Skill "${item.name}" has no description. ` +
155
+ `The description is the skill's trigger text; it is required.`,
156
+ );
157
+ }
158
+ resolved.push(item);
159
+ }
160
+ }
161
+ const seen = new Set<string>();
162
+ for (const skill of resolved) {
163
+ if (seen.has(skill.name)) {
164
+ throw new Error(`Duplicate skill name: "${skill.name}".`);
165
+ }
166
+ seen.add(skill.name);
167
+ }
168
+ return resolved;
169
+ }
170
+
171
+ /** True when any resolved skill carries support files beyond SKILL.md. */
172
+ export function skillsHaveSupportFiles(skills: AgentSkill[]): boolean {
173
+ return skills.some(
174
+ (skill) => skill.files && Object.keys(skill.files).length > 0,
175
+ );
176
+ }
177
+
178
+ /** Collect `skills/{name}/{relPath}` entries for every skill support file. */
179
+ export function skillSupportFileEntries(
180
+ skills: AgentSkill[],
181
+ ): Array<{ path: string; data: Uint8Array }> {
182
+ const entries: Array<{ path: string; data: Uint8Array }> = [];
183
+ for (const skill of skills) {
184
+ for (const [relPath, data] of Object.entries(skill.files ?? {})) {
185
+ if (relPath.split("/").some((part) => part === ".." || part === "")) {
186
+ throw new Error(
187
+ `Skill "${skill.name}" file path escapes the skill directory: ${relPath}`,
188
+ );
189
+ }
190
+ entries.push({ path: `skills/${skill.name}/${relPath}`, data });
191
+ }
192
+ }
193
+ return entries;
194
+ }
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Node-only skill seeding: directory loading and the memory-repo git push.
3
+ *
4
+ * `skill-loading.ts` owns the portable core (types, validation, SKILL.md
5
+ * parsing, block mapping). This module owns everything that touches the
6
+ * filesystem or spawns git, and stays behind the package root so the
7
+ * portable `/client` entry never pulls in Node builtins.
8
+ */
9
+
10
+ import { readFile, readdir, stat, mkdtemp, rm, mkdir, writeFile } from "node:fs/promises";
11
+ import { tmpdir } from "node:os";
12
+ import { basename, dirname, join, relative, sep } from "node:path";
13
+ import { execFile } from "node:child_process";
14
+ import { promisify } from "node:util";
15
+
16
+ import {
17
+ assertValidSkillName,
18
+ parseSkillMarkdown,
19
+ skillSupportFileEntries,
20
+ type AgentSkill,
21
+ } from "./skill-loading.js";
22
+
23
+ const run = promisify(execFile);
24
+
25
+ /** Load one skill directory from disk. */
26
+ export async function loadSkillDirectory(dirPath: string): Promise<AgentSkill> {
27
+ const dirStat = await stat(dirPath).catch(() => null);
28
+ if (!dirStat?.isDirectory()) {
29
+ throw new Error(`Skill path is not a directory: ${dirPath}`);
30
+ }
31
+
32
+ const skillMd = await readFile(join(dirPath, "SKILL.md"), "utf-8").catch(
33
+ () => null,
34
+ );
35
+ if (skillMd === null) {
36
+ throw new Error(`Skill directory has no SKILL.md: ${dirPath}`);
37
+ }
38
+
39
+ const parsed = parseSkillMarkdown(skillMd);
40
+ const name = parsed.name ?? basename(dirPath);
41
+ assertValidSkillName(name);
42
+ if (!parsed.description) {
43
+ throw new Error(
44
+ `SKILL.md in ${dirPath} has no frontmatter description. ` +
45
+ `The description is the skill's trigger text; it is required.`,
46
+ );
47
+ }
48
+
49
+ // Collect support files (everything except SKILL.md), preserving layout.
50
+ const files: Record<string, Uint8Array> = {};
51
+ const walk = async (current: string): Promise<void> => {
52
+ for (const entry of await readdir(current, { withFileTypes: true })) {
53
+ const full = join(current, entry.name);
54
+ if (entry.isDirectory()) {
55
+ await walk(full);
56
+ } else if (entry.isFile()) {
57
+ const rel = relative(dirPath, full).split(sep).join("/");
58
+ if (rel === "SKILL.md") continue;
59
+ files[rel] = new Uint8Array(await readFile(full));
60
+ }
61
+ }
62
+ };
63
+ await walk(dirPath);
64
+
65
+ return {
66
+ name,
67
+ description: parsed.description,
68
+ instructions: parsed.body.replace(/^\s+/, ""),
69
+ ...(Object.keys(files).length > 0 ? { files } : {}),
70
+ };
71
+ }
72
+
73
+ export interface SkillFilesPushTarget {
74
+ apiBaseUrl: string;
75
+ apiKey: string;
76
+ agentId: string;
77
+ }
78
+
79
+ /**
80
+ * Push skill support files into a new agent's memory git repo.
81
+ *
82
+ * SKILL.md rides the create-agent request as a memory block; everything else
83
+ * in a skill directory (scripts/, references/, ...) has no block
84
+ * representation and exactly one write channel: the agent's memory git
85
+ * remote at `{apiBaseUrl}/v1/git/{agentId}/state.git`. This function owns
86
+ * that one commit: shallow clone, write files, commit, push (with one
87
+ * pull --rebase retry in case the server committed between clone and push).
88
+ */
89
+ export async function pushSkillSupportFiles(
90
+ target: SkillFilesPushTarget,
91
+ skills: AgentSkill[],
92
+ ): Promise<void> {
93
+ const entries = skillSupportFileEntries(skills);
94
+ if (entries.length === 0) return;
95
+
96
+ const base = target.apiBaseUrl.replace(/\/+$/, "");
97
+ const remote = `${base}/v1/git/${target.agentId}/state.git`;
98
+ // Credentials travel via a one-shot Authorization header, not the URL, so
99
+ // they cannot leak into error messages or the cloned repo's config.
100
+ const authHeader = `Authorization: Basic ${Buffer.from(`x:${target.apiKey}`).toString("base64")}`;
101
+ const gitEnv = {
102
+ ...process.env,
103
+ GIT_TERMINAL_PROMPT: "0",
104
+ GIT_AUTHOR_NAME: "letta-agent-sdk",
105
+ GIT_AUTHOR_EMAIL: "sdk@letta.com",
106
+ GIT_COMMITTER_NAME: "letta-agent-sdk",
107
+ GIT_COMMITTER_EMAIL: "sdk@letta.com",
108
+ };
109
+ const git = (args: string[], cwd?: string) =>
110
+ run("git", ["-c", `http.extraHeader=${authHeader}`, ...args], {
111
+ env: gitEnv,
112
+ ...(cwd ? { cwd } : {}),
113
+ });
114
+
115
+ const work = await mkdtemp(join(tmpdir(), "letta-skill-seed-"));
116
+ try {
117
+ await git(["clone", "--quiet", "--depth", "1", remote, work]);
118
+ for (const entry of entries) {
119
+ const filePath = join(work, entry.path);
120
+ await mkdir(dirname(filePath), { recursive: true });
121
+ await writeFile(filePath, entry.data);
122
+ }
123
+ await git(["add", "-A"], work);
124
+ await git(["commit", "--quiet", "-m", "feat: seed skill support files"], work);
125
+ try {
126
+ await git(["push", "--quiet", "origin", "HEAD"], work);
127
+ } catch {
128
+ await git(["pull", "--quiet", "--rebase", "origin", "HEAD"], work);
129
+ await git(["push", "--quiet", "origin", "HEAD"], work);
130
+ }
131
+ } catch (error) {
132
+ throw new Error(
133
+ `Agent ${target.agentId} was created, but pushing skill support files ` +
134
+ `to its memory repo failed: ${error instanceof Error ? error.message : String(error)}`,
135
+ );
136
+ } finally {
137
+ await rm(work, { recursive: true, force: true });
138
+ }
139
+ }
package/src/types.ts CHANGED
@@ -209,6 +209,12 @@ export type MemoryItem =
209
209
  | CreateBlock // Custom block: { label, value, description? }
210
210
  | BlockReference; // Shared block reference: { blockId }
211
211
 
212
+ // Skill seeding types (AgentSkill, SkillItem) live beside their
213
+ // implementation in skill-loading.ts and are re-exported from the package
214
+ // root.
215
+ import type { SkillItem } from "./skill-loading.js";
216
+ export type { AgentSkill, SkillItem } from "./skill-loading.js";
217
+
212
218
  /**
213
219
  * Default memory block preset names.
214
220
  */
@@ -408,105 +414,28 @@ export type LettaCodeClientOptions =
408
414
  | LettaCodeRemoteClientOptions
409
415
  | LettaCodeCloudClientOptions;
410
416
 
411
- export interface Repository {
412
- id: string;
413
- name: string;
414
- createdAt: string;
415
- updatedAt: string;
416
- }
417
-
418
- export interface CreateRepositoryParams {
419
- name: string;
420
- }
421
-
422
- export interface ListRepositoriesParams {
423
- limit?: number;
424
- offset?: number;
425
- }
426
-
427
- export interface ListRepositoriesResult {
428
- repositories: Repository[];
429
- hasNextPage: boolean;
430
- }
431
-
432
- export interface RepositoryResource {
433
- type: "repository";
434
- repositoryId: string;
435
- /**
436
- * Whether to trigger a system-prompt recompile after attaching (and after
437
- * detaching on cleanup) so the session's conversation does not retain
438
- * stale repository projections. Defaults to `true`.
439
- */
440
- recompile?: boolean;
441
- }
442
-
443
- export interface RepositoryFileEntry {
444
- path: string;
445
- type: "file" | "directory";
446
- }
447
-
448
- export interface ListRepositoryFilesParams {
449
- pathPrefix?: string;
450
- depth?: number;
451
- ref?: string;
452
- }
453
-
454
- export interface ListRepositoryFilesResult {
455
- files: RepositoryFileEntry[];
456
- ref: string;
457
- }
458
-
459
- export interface CreateRepositoryFileParams {
460
- path: string;
461
- content: string;
462
- }
463
-
464
- export interface RepositoryFile {
465
- path: string;
466
- content: string;
467
- contentSha256: string;
468
- ref?: string;
469
- }
470
-
471
- export interface UpdateRepositoryFileParams {
472
- path: string;
473
- content?: string;
474
- newPath?: string;
475
- precondition?: {
476
- contentSha256: string;
477
- };
478
- }
479
-
480
- export interface RepositoryFileMutationResult {
481
- path: string;
482
- contentSha256: string;
483
- commitSha: string;
484
- }
485
-
486
- export interface DeleteRepositoryFileParams {
487
- path: string;
488
- }
489
-
490
- export interface DeleteRepositoryFileResult {
491
- success: boolean;
492
- commitSha: string;
493
- }
494
-
495
- export interface RepositoryVersion {
496
- sha: string;
497
- message: string;
498
- timestamp: string;
499
- author_name: string | null;
500
- }
501
-
502
- export interface ListRepositoryVersionsParams {
503
- path?: string;
504
- limit?: number;
505
- }
506
-
507
- export interface GetRepositoryVersionParams {
508
- path: string;
509
- }
417
+ // Letta-hosted repository API types live beside their implementation in
418
+ // repository-types.ts and are re-exported here for compatibility.
419
+ import type { RepositoryResource } from "./repository-types.js";
420
+ export type {
421
+ Repository,
422
+ CreateRepositoryParams,
423
+ ListRepositoriesParams,
424
+ ListRepositoriesResult,
425
+ RepositoryResource,
426
+ RepositoryFileEntry,
427
+ ListRepositoryFilesParams,
428
+ ListRepositoryFilesResult,
429
+ CreateRepositoryFileParams,
430
+ RepositoryFile,
431
+ UpdateRepositoryFileParams,
432
+ RepositoryFileMutationResult,
433
+ DeleteRepositoryFileParams,
434
+ DeleteRepositoryFileResult,
435
+ RepositoryVersion,
436
+ ListRepositoryVersionsParams,
437
+ GetRepositoryVersionParams,
438
+ } from "./repository-types.js";
510
439
 
511
440
  // ═══════════════════════════════════════════════════════════════
512
441
  // SESSION OPTIONS
@@ -951,6 +880,19 @@ export interface CreateAgentOptions {
951
880
  */
952
881
  memory?: MemoryItem[];
953
882
 
883
+ /**
884
+ * Skills to seed into the agent's memory filesystem at creation. Each item
885
+ * is a path to a skill directory containing SKILL.md (Node runtimes only)
886
+ * or an inline {@link AgentSkill}.
887
+ *
888
+ * SKILL.md instructions ride the create request itself (as the memory
889
+ * block labeled `skills/{name}`) and are present from the agent's first
890
+ * turn. Skill support files (scripts, references) are pushed to the
891
+ * agent's memory repo immediately after creation; that second step
892
+ * currently requires the Cloud backend. Requires memfs (the default).
893
+ */
894
+ skills?: SkillItem[];
895
+
954
896
  /** @deprecated Prefer a personality preset or a system memory file. */
955
897
  persona?: string;
956
898
 
@@ -1038,7 +980,7 @@ export interface CreateAgentOptions {
1038
980
  */
1039
981
  export interface SDKInitMessage {
1040
982
  type: "init";
1041
- agentId: string;
983
+ agentId: string | null;
1042
984
  sessionId: string;
1043
985
  conversationId: string;
1044
986
  model: string;