@greppleai/grip-agent-core 0.1.5 → 0.1.7

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 (61) hide show
  1. package/dist/agent-loop.d.ts.map +1 -1
  2. package/dist/agent-loop.js.map +1 -1
  3. package/dist/agent.d.ts +7 -0
  4. package/dist/agent.d.ts.map +1 -1
  5. package/dist/agent.js +2 -27
  6. package/dist/agent.js.map +1 -1
  7. package/dist/harness/agent-harness.d.ts.map +1 -1
  8. package/dist/harness/agent-harness.js +7 -20
  9. package/dist/harness/agent-harness.js.map +1 -1
  10. package/dist/harness/compaction/branch-summarization.d.ts.map +1 -1
  11. package/dist/harness/compaction/branch-summarization.js.map +1 -1
  12. package/dist/harness/compaction/compaction.d.ts.map +1 -1
  13. package/dist/harness/compaction/compaction.js.map +1 -1
  14. package/dist/harness/compaction/utils.d.ts.map +1 -1
  15. package/dist/harness/compaction/utils.js.map +1 -1
  16. package/dist/harness/env/nodejs.d.ts.map +1 -1
  17. package/dist/harness/env/nodejs.js +0 -3
  18. package/dist/harness/env/nodejs.js.map +1 -1
  19. package/dist/harness/messages.d.ts.map +1 -1
  20. package/dist/harness/messages.js.map +1 -1
  21. package/dist/harness/prompt-templates.d.ts.map +1 -1
  22. package/dist/harness/prompt-templates.js.map +1 -1
  23. package/dist/harness/session/jsonl-errors.d.ts.map +1 -1
  24. package/dist/harness/session/jsonl-errors.js +0 -10
  25. package/dist/harness/session/jsonl-errors.js.map +1 -1
  26. package/dist/harness/session/jsonl-repo.d.ts.map +1 -1
  27. package/dist/harness/session/jsonl-repo.js +1 -4
  28. package/dist/harness/session/jsonl-repo.js.map +1 -1
  29. package/dist/harness/session/jsonl-storage.d.ts.map +1 -1
  30. package/dist/harness/session/jsonl-storage.js +1 -11
  31. package/dist/harness/session/jsonl-storage.js.map +1 -1
  32. package/dist/harness/session/memory-repo.d.ts.map +1 -1
  33. package/dist/harness/session/memory-repo.js +3 -1
  34. package/dist/harness/session/memory-repo.js.map +1 -1
  35. package/dist/harness/session/memory-storage.d.ts.map +1 -1
  36. package/dist/harness/session/memory-storage.js +0 -5
  37. package/dist/harness/session/memory-storage.js.map +1 -1
  38. package/dist/harness/session/repo-utils.d.ts.map +1 -1
  39. package/dist/harness/session/repo-utils.js.map +1 -1
  40. package/dist/harness/session/session.d.ts.map +1 -1
  41. package/dist/harness/session/session.js +0 -1
  42. package/dist/harness/session/session.js.map +1 -1
  43. package/dist/harness/session/uuid.d.ts.map +1 -1
  44. package/dist/harness/session/uuid.js.map +1 -1
  45. package/dist/harness/skills.d.ts.map +1 -1
  46. package/dist/harness/skills.js.map +1 -1
  47. package/dist/harness/system-prompt.d.ts.map +1 -1
  48. package/dist/harness/system-prompt.js.map +1 -1
  49. package/dist/harness/types.d.ts.map +1 -1
  50. package/dist/harness/types.js +0 -13
  51. package/dist/harness/types.js.map +1 -1
  52. package/dist/harness/utils/shell-output.d.ts.map +1 -1
  53. package/dist/harness/utils/shell-output.js.map +1 -1
  54. package/dist/harness/utils/truncate.d.ts.map +1 -1
  55. package/dist/harness/utils/truncate.js.map +1 -1
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/node.d.ts.map +1 -1
  58. package/dist/proxy.d.ts.map +1 -1
  59. package/dist/proxy.js.map +1 -1
  60. package/dist/types.d.ts.map +1 -1
  61. package/package.json +10 -10
@@ -1 +1 @@
1
- {"version":3,"file":"memory-storage.js","sourceRoot":"","sources":["../../../src/harness/session/memory-storage.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype LeafEntry,\n\tSessionError,\n\ttype SessionMetadata,\n\ttype SessionStorage,\n\ttype SessionTreeEntry,\n\ttype SessionTreeEntryOfType,\n} from \"../types.ts\";\nimport { uuidv7 } from \"./uuid.ts\";\n\nfunction updateLabelCache(labelsById: Map<string, string>, entry: SessionTreeEntry): void {\n\tif (entry.type !== \"label\") return;\n\tconst label = entry.label?.trim();\n\tif (label) {\n\t\tlabelsById.set(entry.targetId, label);\n\t} else {\n\t\tlabelsById.delete(entry.targetId);\n\t}\n}\n\nfunction buildLabelsById(entries: SessionTreeEntry[]): Map<string, string> {\n\tconst labelsById = new Map<string, string>();\n\tfor (const entry of entries) {\n\t\tupdateLabelCache(labelsById, entry);\n\t}\n\treturn labelsById;\n}\n\ninterface SessionEntryIdLookup {\n\thas(id: string): boolean;\n}\n\nfunction generateEntryId(byId: SessionEntryIdLookup): string {\n\tfor (let i = 0; i < 100; i++) {\n\t\t// The uuidv7 prefix is timestamp-derived and nearly constant between calls,\n\t\t// so short ids must come from the random tail.\n\t\tconst id = uuidv7().slice(-8);\n\t\tif (!byId.has(id)) return id;\n\t}\n\treturn uuidv7();\n}\n\nfunction leafIdAfterEntry(entry: SessionTreeEntry): string | null {\n\treturn entry.type === \"leaf\" ? entry.targetId : entry.id;\n}\n\ninterface InMemorySessionStorageOptions<TMetadata> {\n\tentries?: SessionTreeEntry[];\n\tmetadata?: TMetadata;\n}\n\nexport class InMemorySessionStorage<TMetadata extends SessionMetadata = SessionMetadata>\n\timplements SessionStorage<TMetadata>\n{\n\tprivate readonly metadata: TMetadata;\n\tprivate entries: SessionTreeEntry[];\n\tprivate byId: Map<string, SessionTreeEntry>;\n\tprivate labelsById: Map<string, string>;\n\tprivate leafId: string | null;\n\n\tconstructor(options?: InMemorySessionStorageOptions<TMetadata>) {\n\t\tthis.entries = options?.entries ? [...options.entries] : [];\n\t\tthis.byId = new Map(this.entries.map((entry) => [entry.id, entry]));\n\t\tthis.labelsById = buildLabelsById(this.entries);\n\t\tthis.leafId = null;\n\t\tfor (const entry of this.entries) this.leafId = leafIdAfterEntry(entry);\n\t\tif (this.leafId !== null && !this.byId.has(this.leafId)) {\n\t\t\tthrow new SessionError(\"invalid_session\", `Entry ${this.leafId} not found`);\n\t\t}\n\t\tthis.metadata = options?.metadata ?? ({ id: uuidv7(), createdAt: new Date().toISOString() } as TMetadata);\n\t}\n\n\tasync getMetadata(): Promise<TMetadata> {\n\t\treturn this.metadata;\n\t}\n\n\tasync getLeafId(): Promise<string | null> {\n\t\tif (this.leafId !== null && !this.byId.has(this.leafId)) {\n\t\t\tthrow new SessionError(\"invalid_session\", `Entry ${this.leafId} not found`);\n\t\t}\n\t\treturn this.leafId;\n\t}\n\n\tasync setLeafId(leafId: string | null): Promise<void> {\n\t\tif (leafId !== null && !this.byId.has(leafId)) {\n\t\t\tthrow new SessionError(\"not_found\", `Entry ${leafId} not found`);\n\t\t}\n\t\tconst entry: LeafEntry = {\n\t\t\ttype: \"leaf\",\n\t\t\tid: generateEntryId(this.byId),\n\t\t\tparentId: this.leafId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\ttargetId: leafId,\n\t\t};\n\t\tthis.entries.push(entry);\n\t\tthis.byId.set(entry.id, entry);\n\t\tthis.leafId = leafId;\n\t}\n\n\tasync createEntryId(): Promise<string> {\n\t\treturn generateEntryId(this.byId);\n\t}\n\n\tasync appendEntry(entry: SessionTreeEntry): Promise<void> {\n\t\tthis.entries.push(entry);\n\t\tthis.byId.set(entry.id, entry);\n\t\tupdateLabelCache(this.labelsById, entry);\n\t\tthis.leafId = leafIdAfterEntry(entry);\n\t}\n\n\tasync getEntry(id: string): Promise<SessionTreeEntry | undefined> {\n\t\treturn this.byId.get(id);\n\t}\n\n\tasync findEntries<TType extends SessionTreeEntry[\"type\"]>(\n\t\ttype: TType,\n\t): Promise<Array<SessionTreeEntryOfType<TType>>> {\n\t\treturn this.entries.filter((entry): entry is SessionTreeEntryOfType<TType> => entry.type === type);\n\t}\n\n\tasync getLabel(id: string): Promise<string | undefined> {\n\t\treturn this.labelsById.get(id);\n\t}\n\n\tasync getPathToRoot(leafId: string | null): Promise<SessionTreeEntry[]> {\n\t\tif (leafId === null) return [];\n\t\tconst path: SessionTreeEntry[] = [];\n\t\tlet current = this.byId.get(leafId);\n\t\tif (!current) throw new SessionError(\"not_found\", `Entry ${leafId} not found`);\n\t\twhile (current) {\n\t\t\tpath.unshift(current);\n\t\t\tif (!current.parentId) break;\n\t\t\tconst parent = this.byId.get(current.parentId);\n\t\t\tif (!parent) throw new SessionError(\"invalid_session\", `Entry ${current.parentId} not found`);\n\t\t\tcurrent = parent;\n\t\t}\n\t\treturn path;\n\t}\n\n\tasync getEntries(): Promise<SessionTreeEntry[]> {\n\t\treturn [...this.entries];\n\t}\n}\n"]}
1
+ {"version":3,"file":"memory-storage.js","sourceRoot":"","sources":["../../../src/harness/session/memory-storage.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype LeafEntry,\n\tSessionError,\n\ttype SessionMetadata,\n\ttype SessionStorage,\n\ttype SessionTreeEntry,\n\ttype SessionTreeEntryOfType,\n} from \"../types.ts\";\nimport { uuidv7 } from \"./uuid.ts\";\n\nfunction updateLabelCache(labelsById: Map<string, string>, entry: SessionTreeEntry): void {\n\tif (entry.type !== \"label\") return;\n\tconst label = entry.label?.trim();\n\tif (label) {\n\t\tlabelsById.set(entry.targetId, label);\n\t} else {\n\t\tlabelsById.delete(entry.targetId);\n\t}\n}\n\nfunction buildLabelsById(entries: SessionTreeEntry[]): Map<string, string> {\n\tconst labelsById = new Map<string, string>();\n\tfor (const entry of entries) {\n\t\tupdateLabelCache(labelsById, entry);\n\t}\n\treturn labelsById;\n}\n\ninterface SessionEntryIdLookup {\n\thas(id: string): boolean;\n}\n\nfunction generateEntryId(byId: SessionEntryIdLookup): string {\n\tfor (let i = 0; i < 100; i++) {\n\t\t// The uuidv7 prefix is timestamp-derived and nearly constant between calls,\n\t\t// so short ids must come from the random tail.\n\t\tconst id = uuidv7().slice(-8);\n\t\tif (!byId.has(id)) return id;\n\t}\n\treturn uuidv7();\n}\n\nfunction leafIdAfterEntry(entry: SessionTreeEntry): string | null {\n\treturn entry.type === \"leaf\" ? entry.targetId : entry.id;\n}\n\ninterface InMemorySessionStorageOptions<TMetadata> {\n\tentries?: SessionTreeEntry[];\n\tmetadata?: TMetadata;\n}\n\nexport class InMemorySessionStorage<TMetadata extends SessionMetadata = SessionMetadata>\n\timplements SessionStorage<TMetadata>\n{\n\tprivate readonly metadata: TMetadata;\n\tprivate entries: SessionTreeEntry[];\n\tprivate byId: Map<string, SessionTreeEntry>;\n\tprivate labelsById: Map<string, string>;\n\tprivate leafId: string | null;\n\n\tconstructor(options?: InMemorySessionStorageOptions<TMetadata>) {\n\t\tthis.entries = options?.entries ? [...options.entries] : [];\n\t\tthis.byId = new Map(this.entries.map((entry) => [entry.id, entry]));\n\t\tthis.labelsById = buildLabelsById(this.entries);\n\t\tthis.leafId = null;\n\t\tfor (const entry of this.entries) this.leafId = leafIdAfterEntry(entry);\n\t\tif (this.leafId !== null && !this.byId.has(this.leafId)) {\n\t\t\tthrow new SessionError(\"invalid_session\", `Entry ${this.leafId} not found`);\n\t\t}\n\t\tthis.metadata = options?.metadata ?? ({ id: uuidv7(), createdAt: new Date().toISOString() } as TMetadata);\n\t}\n\n\tasync getMetadata(): Promise<TMetadata> {\n\t\treturn this.metadata;\n\t}\n\n\tasync getLeafId(): Promise<string | null> {\n\t\tif (this.leafId !== null && !this.byId.has(this.leafId)) {\n\t\t\tthrow new SessionError(\"invalid_session\", `Entry ${this.leafId} not found`);\n\t\t}\n\t\treturn this.leafId;\n\t}\n\n\tasync setLeafId(leafId: string | null): Promise<void> {\n\t\tif (leafId !== null && !this.byId.has(leafId)) {\n\t\t\tthrow new SessionError(\"not_found\", `Entry ${leafId} not found`);\n\t\t}\n\t\tconst entry: LeafEntry = {\n\t\t\ttype: \"leaf\",\n\t\t\tid: generateEntryId(this.byId),\n\t\t\tparentId: this.leafId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\ttargetId: leafId,\n\t\t};\n\t\tthis.entries.push(entry);\n\t\tthis.byId.set(entry.id, entry);\n\t\tthis.leafId = leafId;\n\t}\n\n\tasync createEntryId(): Promise<string> {\n\t\treturn generateEntryId(this.byId);\n\t}\n\n\tasync appendEntry(entry: SessionTreeEntry): Promise<void> {\n\t\tthis.entries.push(entry);\n\t\tthis.byId.set(entry.id, entry);\n\t\tupdateLabelCache(this.labelsById, entry);\n\t\tthis.leafId = leafIdAfterEntry(entry);\n\t}\n\n\tasync getEntry(id: string): Promise<SessionTreeEntry | undefined> {\n\t\treturn this.byId.get(id);\n\t}\n\n\tasync findEntries<TType extends SessionTreeEntry[\"type\"]>(\n\t\ttype: TType,\n\t): Promise<Array<SessionTreeEntryOfType<TType>>> {\n\t\treturn this.entries.filter((entry): entry is SessionTreeEntryOfType<TType> => entry.type === type);\n\t}\n\n\tasync getLabel(id: string): Promise<string | undefined> {\n\t\treturn this.labelsById.get(id);\n\t}\n\n\tasync getPathToRoot(leafId: string | null): Promise<SessionTreeEntry[]> {\n\t\tif (leafId === null) return [];\n\t\tconst path: SessionTreeEntry[] = [];\n\t\tlet current = this.byId.get(leafId);\n\t\tif (!current) throw new SessionError(\"not_found\", `Entry ${leafId} not found`);\n\t\twhile (current) {\n\t\t\tpath.unshift(current);\n\t\t\tif (!current.parentId) break;\n\t\t\tconst parent = this.byId.get(current.parentId);\n\t\t\tif (!parent) throw new SessionError(\"invalid_session\", `Entry ${current.parentId} not found`);\n\t\t\tcurrent = parent;\n\t\t}\n\t\treturn path;\n\t}\n\n\tasync getEntries(): Promise<SessionTreeEntry[]> {\n\t\treturn [...this.entries];\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"repo-utils.d.ts","sourceRoot":"","sources":["../../../src/harness/session/repo-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,SAAS,EACd,KAAK,MAAM,EAEX,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,wBAAgB,SAAS,CAAC,SAAS,SAAS,eAAe,EAAE,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAEnH;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAM7G;AAED,wBAAsB,gBAAgB,CACrC,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,kBAAkB,GACzB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAgB7B","sourcesContent":["import {\n\ttype FileError,\n\ttype Result,\n\tSessionError,\n\ttype SessionForkOptions,\n\ttype SessionMetadata,\n\ttype SessionStorage,\n\ttype SessionTreeEntry,\n} from \"../types.ts\";\nimport { Session } from \"./session.ts\";\nimport { uuidv7 } from \"./uuid.ts\";\n\nexport function createSessionId(): string {\n\treturn uuidv7();\n}\n\nexport function createTimestamp(): string {\n\treturn new Date().toISOString();\n}\n\nexport function toSession<TMetadata extends SessionMetadata>(storage: SessionStorage<TMetadata>): Session<TMetadata> {\n\treturn new Session(storage);\n}\n\nexport function getFileSystemResultOrThrow<TValue>(result: Result<TValue, FileError>, message: string): TValue {\n\tif (!result.ok) {\n\t\tconst code = result.error.code === \"not_found\" ? \"not_found\" : \"storage\";\n\t\tthrow new SessionError(code, `${message}: ${result.error.message}`, result.error);\n\t}\n\treturn result.value;\n}\n\nexport async function getEntriesToFork(\n\tstorage: SessionStorage,\n\toptions: SessionForkOptions,\n): Promise<SessionTreeEntry[]> {\n\tif (!options.entryId) return storage.getEntries();\n\tconst target = await storage.getEntry(options.entryId);\n\tif (!target) {\n\t\tthrow new SessionError(\"invalid_fork_target\", `Entry ${options.entryId} not found`);\n\t}\n\tlet effectiveLeafId: string | null;\n\tif ((options.position ?? \"before\") === \"at\") {\n\t\teffectiveLeafId = target.id;\n\t} else {\n\t\tif (target.type !== \"message\" || target.message.role !== \"user\") {\n\t\t\tthrow new SessionError(\"invalid_fork_target\", `Entry ${options.entryId} is not a user message`);\n\t\t}\n\t\teffectiveLeafId = target.parentId;\n\t}\n\treturn storage.getPathToRoot(effectiveLeafId);\n}\n"]}
1
+ {"version":3,"file":"repo-utils.d.ts","sourceRoot":"","sources":["../../../src/harness/session/repo-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,SAAS,EACd,KAAK,MAAM,EAEX,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,wBAAgB,SAAS,CAAC,SAAS,SAAS,eAAe,EAAE,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAEnH;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAM7G;AAED,wBAAsB,gBAAgB,CACrC,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,kBAAkB,GACzB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAgB7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"repo-utils.js","sourceRoot":"","sources":["../../../src/harness/session/repo-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,YAAY,GAKZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,MAAM,UAAU,eAAe,GAAW;IACzC,OAAO,MAAM,EAAE,CAAC;AAAA,CAChB;AAED,MAAM,UAAU,eAAe,GAAW;IACzC,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAAA,CAChC;AAED,MAAM,UAAU,SAAS,CAAoC,OAAkC,EAAsB;IACpH,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;AAAA,CAC5B;AAED,MAAM,UAAU,0BAA0B,CAAS,MAAiC,EAAE,OAAe,EAAU;IAC9G,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QAChB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;QACzE,MAAM,IAAI,YAAY,CAAC,IAAI,EAAE,GAAG,OAAO,KAAK,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC;AAAA,CACpB;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACrC,OAAuB,EACvB,OAA2B,EACG;IAC9B,IAAI,CAAC,OAAO,CAAC,OAAO;QAAE,OAAO,OAAO,CAAC,UAAU,EAAE,CAAC;IAClD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,MAAM,IAAI,YAAY,CAAC,qBAAqB,EAAE,SAAS,OAAO,CAAC,OAAO,YAAY,CAAC,CAAC;IACrF,CAAC;IACD,IAAI,eAA8B,CAAC;IACnC,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7C,eAAe,GAAG,MAAM,CAAC,EAAE,CAAC;IAC7B,CAAC;SAAM,CAAC;QACP,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACjE,MAAM,IAAI,YAAY,CAAC,qBAAqB,EAAE,SAAS,OAAO,CAAC,OAAO,wBAAwB,CAAC,CAAC;QACjG,CAAC;QACD,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAC;IACnC,CAAC;IACD,OAAO,OAAO,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC;AAAA,CAC9C","sourcesContent":["import {\n\ttype FileError,\n\ttype Result,\n\tSessionError,\n\ttype SessionForkOptions,\n\ttype SessionMetadata,\n\ttype SessionStorage,\n\ttype SessionTreeEntry,\n} from \"../types.ts\";\nimport { Session } from \"./session.ts\";\nimport { uuidv7 } from \"./uuid.ts\";\n\nexport function createSessionId(): string {\n\treturn uuidv7();\n}\n\nexport function createTimestamp(): string {\n\treturn new Date().toISOString();\n}\n\nexport function toSession<TMetadata extends SessionMetadata>(storage: SessionStorage<TMetadata>): Session<TMetadata> {\n\treturn new Session(storage);\n}\n\nexport function getFileSystemResultOrThrow<TValue>(result: Result<TValue, FileError>, message: string): TValue {\n\tif (!result.ok) {\n\t\tconst code = result.error.code === \"not_found\" ? \"not_found\" : \"storage\";\n\t\tthrow new SessionError(code, `${message}: ${result.error.message}`, result.error);\n\t}\n\treturn result.value;\n}\n\nexport async function getEntriesToFork(\n\tstorage: SessionStorage,\n\toptions: SessionForkOptions,\n): Promise<SessionTreeEntry[]> {\n\tif (!options.entryId) return storage.getEntries();\n\tconst target = await storage.getEntry(options.entryId);\n\tif (!target) {\n\t\tthrow new SessionError(\"invalid_fork_target\", `Entry ${options.entryId} not found`);\n\t}\n\tlet effectiveLeafId: string | null;\n\tif ((options.position ?? \"before\") === \"at\") {\n\t\teffectiveLeafId = target.id;\n\t} else {\n\t\tif (target.type !== \"message\" || target.message.role !== \"user\") {\n\t\t\tthrow new SessionError(\"invalid_fork_target\", `Entry ${options.entryId} is not a user message`);\n\t\t}\n\t\teffectiveLeafId = target.parentId;\n\t}\n\treturn storage.getPathToRoot(effectiveLeafId);\n}\n"]}
1
+ {"version":3,"file":"repo-utils.js","sourceRoot":"","sources":["../../../src/harness/session/repo-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,YAAY,GAKZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,MAAM,UAAU,eAAe;IAC9B,OAAO,MAAM,EAAE,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,eAAe;IAC9B,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,SAAS,CAAoC,OAAkC;IAC9F,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAS,MAAiC,EAAE,OAAe;IACpG,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QAChB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;QACzE,MAAM,IAAI,YAAY,CAAC,IAAI,EAAE,GAAG,OAAO,KAAK,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC;AACrB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACrC,OAAuB,EACvB,OAA2B;IAE3B,IAAI,CAAC,OAAO,CAAC,OAAO;QAAE,OAAO,OAAO,CAAC,UAAU,EAAE,CAAC;IAClD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,MAAM,IAAI,YAAY,CAAC,qBAAqB,EAAE,SAAS,OAAO,CAAC,OAAO,YAAY,CAAC,CAAC;IACrF,CAAC;IACD,IAAI,eAA8B,CAAC;IACnC,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7C,eAAe,GAAG,MAAM,CAAC,EAAE,CAAC;IAC7B,CAAC;SAAM,CAAC;QACP,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACjE,MAAM,IAAI,YAAY,CAAC,qBAAqB,EAAE,SAAS,OAAO,CAAC,OAAO,wBAAwB,CAAC,CAAC;QACjG,CAAC;QACD,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAC;IACnC,CAAC;IACD,OAAO,OAAO,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC;AAC/C,CAAC","sourcesContent":["import {\n\ttype FileError,\n\ttype Result,\n\tSessionError,\n\ttype SessionForkOptions,\n\ttype SessionMetadata,\n\ttype SessionStorage,\n\ttype SessionTreeEntry,\n} from \"../types.ts\";\nimport { Session } from \"./session.ts\";\nimport { uuidv7 } from \"./uuid.ts\";\n\nexport function createSessionId(): string {\n\treturn uuidv7();\n}\n\nexport function createTimestamp(): string {\n\treturn new Date().toISOString();\n}\n\nexport function toSession<TMetadata extends SessionMetadata>(storage: SessionStorage<TMetadata>): Session<TMetadata> {\n\treturn new Session(storage);\n}\n\nexport function getFileSystemResultOrThrow<TValue>(result: Result<TValue, FileError>, message: string): TValue {\n\tif (!result.ok) {\n\t\tconst code = result.error.code === \"not_found\" ? \"not_found\" : \"storage\";\n\t\tthrow new SessionError(code, `${message}: ${result.error.message}`, result.error);\n\t}\n\treturn result.value;\n}\n\nexport async function getEntriesToFork(\n\tstorage: SessionStorage,\n\toptions: SessionForkOptions,\n): Promise<SessionTreeEntry[]> {\n\tif (!options.entryId) return storage.getEntries();\n\tconst target = await storage.getEntry(options.entryId);\n\tif (!target) {\n\t\tthrow new SessionError(\"invalid_fork_target\", `Entry ${options.entryId} not found`);\n\t}\n\tlet effectiveLeafId: string | null;\n\tif ((options.position ?? \"before\") === \"at\") {\n\t\teffectiveLeafId = target.id;\n\t} else {\n\t\tif (target.type !== \"message\" || target.message.role !== \"user\") {\n\t\t\tthrow new SessionError(\"invalid_fork_target\", `Entry ${options.entryId} is not a user message`);\n\t\t}\n\t\teffectiveLeafId = target.parentId;\n\t}\n\treturn storage.getPathToRoot(effectiveLeafId);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/harness/session/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,KAAK,EAQX,cAAc,EAEd,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAEhB,MAAM,aAAa,CAAC;AA0ErB,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,gBAAgB,EAAE,GAAG,cAAc,CAOnF;AAED,qBAAa,OAAO,CAAC,SAAS,SAAS,eAAe,GAAG,eAAe;IACvE,OAAO,CAAC,OAAO,CAA4B;IAE3C,YAAY,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,EAE7C;IAED,WAAW,IAAI,OAAO,CAAC,SAAS,CAAC,CAEhC;IAED,UAAU,IAAI,cAAc,CAAC,SAAS,CAAC,CAEtC;IAED,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAElC;IAED,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAE1D;IAED,UAAU,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAExC;IAEK,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAG5D;IAEK,YAAY,IAAI,OAAO,CAAC,cAAc,CAAC,CAE5C;IAED,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAEhD;IAEK,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAGlD;YAEa,gBAAgB;IAKxB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ1D;IAEK,yBAAyB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQtE;IAEK,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS1E;IAEK,gBAAgB,CAAC,CAAC,GAAG,OAAO,EACjC,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,EACxB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,CAAC,EACX,QAAQ,CAAC,EAAE,OAAO,GAChB,OAAO,CAAC,MAAM,CAAC,CAYjB;IAEK,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAS3E;IAEK,wBAAwB,CAAC,CAAC,GAAG,OAAO,EACzC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GAAG,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,EAChD,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,CAAC,GACT,OAAO,CAAC,MAAM,CAAC,CAWjB;IAEK,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAY9E;IAEK,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQrD;IAEK,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAgB9F;CACD","sourcesContent":["import type { ImageContent, TextContent } from \"@greppleai/grip-ai\";\nimport type { AgentMessage } from \"../../types.ts\";\nimport { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage } from \"../messages.ts\";\nimport type {\n\tBranchSummaryEntry,\n\tCompactionEntry,\n\tCustomEntry,\n\tCustomMessageEntry,\n\tLabelEntry,\n\tMessageEntry,\n\tModelChangeEntry,\n\tSessionContext,\n\tSessionInfoEntry,\n\tSessionMetadata,\n\tSessionMoveSummary,\n\tSessionStorage,\n\tSessionTreeEntry,\n\tThinkingLevelChangeEntry,\n} from \"../types.ts\";\nimport { SessionError } from \"../types.ts\";\n\ninterface SessionContextBuildState {\n\tthinkingLevel: string;\n\tmodel: SessionContext[\"model\"];\n\tcompaction: CompactionEntry | null;\n}\n\nfunction resolveSessionContextState(pathEntries: SessionTreeEntry[]): SessionContextBuildState {\n\tconst state: SessionContextBuildState = { thinkingLevel: \"off\", model: null, compaction: null };\n\tfor (const entry of pathEntries) {\n\t\tswitch (entry.type) {\n\t\t\tcase \"thinking_level_change\":\n\t\t\t\tstate.thinkingLevel = entry.thinkingLevel;\n\t\t\t\tbreak;\n\t\t\tcase \"model_change\":\n\t\t\t\tstate.model = { provider: entry.provider, modelId: entry.modelId };\n\t\t\t\tbreak;\n\t\t\tcase \"message\":\n\t\t\t\tif (entry.message.role === \"assistant\") {\n\t\t\t\t\tstate.model = { provider: entry.message.provider, modelId: entry.message.model };\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"compaction\":\n\t\t\t\tstate.compaction = entry;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn state;\n}\n\nfunction appendSessionEntryMessage(messages: AgentMessage[], entry: SessionTreeEntry): void {\n\tif (entry.type === \"message\") {\n\t\tmessages.push(entry.message as AgentMessage);\n\t\treturn;\n\t}\n\tif (entry.type === \"custom_message\") {\n\t\tmessages.push(\n\t\t\tcreateCustomMessage(\n\t\t\t\tentry.customType,\n\t\t\t\tentry.content as string | (TextContent | ImageContent)[],\n\t\t\t\tentry.display,\n\t\t\t\tentry.details,\n\t\t\t\tentry.timestamp,\n\t\t\t),\n\t\t);\n\t\treturn;\n\t}\n\tif (entry.type === \"branch_summary\" && entry.summary) {\n\t\tmessages.push(createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp));\n\t}\n}\n\nfunction buildSessionMessages(pathEntries: SessionTreeEntry[], compaction: CompactionEntry | null): AgentMessage[] {\n\tconst messages: AgentMessage[] = [];\n\tif (!compaction) {\n\t\tfor (const entry of pathEntries) appendSessionEntryMessage(messages, entry);\n\t\treturn messages;\n\t}\n\tmessages.push(createCompactionSummaryMessage(compaction.summary, compaction.tokensBefore, compaction.timestamp));\n\tconst compactionIdx = pathEntries.findIndex((entry) => entry.type === \"compaction\" && entry.id === compaction.id);\n\tlet foundFirstKept = false;\n\tfor (let index = 0; index < compactionIdx; index++) {\n\t\tconst entry = pathEntries[index]!;\n\t\tif (entry.id === compaction.firstKeptEntryId) foundFirstKept = true;\n\t\tif (foundFirstKept) appendSessionEntryMessage(messages, entry);\n\t}\n\tfor (let index = compactionIdx + 1; index < pathEntries.length; index++) {\n\t\tappendSessionEntryMessage(messages, pathEntries[index]!);\n\t}\n\treturn messages;\n}\n\nexport function buildSessionContext(pathEntries: SessionTreeEntry[]): SessionContext {\n\tconst state = resolveSessionContextState(pathEntries);\n\treturn {\n\t\tmessages: buildSessionMessages(pathEntries, state.compaction),\n\t\tthinkingLevel: state.thinkingLevel,\n\t\tmodel: state.model,\n\t};\n}\n\nexport class Session<TMetadata extends SessionMetadata = SessionMetadata> {\n\tprivate storage: SessionStorage<TMetadata>;\n\n\tconstructor(storage: SessionStorage<TMetadata>) {\n\t\tthis.storage = storage;\n\t}\n\n\tgetMetadata(): Promise<TMetadata> {\n\t\treturn this.storage.getMetadata();\n\t}\n\n\tgetStorage(): SessionStorage<TMetadata> {\n\t\treturn this.storage;\n\t}\n\n\tgetLeafId(): Promise<string | null> {\n\t\treturn this.storage.getLeafId();\n\t}\n\n\tgetEntry(id: string): Promise<SessionTreeEntry | undefined> {\n\t\treturn this.storage.getEntry(id);\n\t}\n\n\tgetEntries(): Promise<SessionTreeEntry[]> {\n\t\treturn this.storage.getEntries();\n\t}\n\n\tasync getBranch(fromId?: string): Promise<SessionTreeEntry[]> {\n\t\tconst leafId = fromId ?? (await this.storage.getLeafId());\n\t\treturn this.storage.getPathToRoot(leafId);\n\t}\n\n\tasync buildContext(): Promise<SessionContext> {\n\t\treturn buildSessionContext(await this.getBranch());\n\t}\n\n\tgetLabel(id: string): Promise<string | undefined> {\n\t\treturn this.storage.getLabel(id);\n\t}\n\n\tasync getSessionName(): Promise<string | undefined> {\n\t\tconst entries = await this.storage.findEntries(\"session_info\");\n\t\treturn entries[entries.length - 1]?.name?.trim() || undefined;\n\t}\n\n\tprivate async appendTypedEntry<TEntry extends SessionTreeEntry>(entry: TEntry): Promise<string> {\n\t\tawait this.storage.appendEntry(entry);\n\t\treturn entry.id;\n\t}\n\n\tasync appendMessage(message: AgentMessage): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"message\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tmessage,\n\t\t} satisfies MessageEntry);\n\t}\n\n\tasync appendThinkingLevelChange(thinkingLevel: string): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"thinking_level_change\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tthinkingLevel,\n\t\t} satisfies ThinkingLevelChangeEntry);\n\t}\n\n\tasync appendModelChange(provider: string, modelId: string): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"model_change\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tprovider,\n\t\t\tmodelId,\n\t\t} satisfies ModelChangeEntry);\n\t}\n\n\tasync appendCompaction<T = unknown>(\n\t\tsummary: string,\n\t\tfirstKeptEntryId: string,\n\t\ttokensBefore: number,\n\t\tdetails?: T,\n\t\tfromHook?: boolean,\n\t): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"compaction\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tsummary,\n\t\t\tfirstKeptEntryId,\n\t\t\ttokensBefore,\n\t\t\tdetails,\n\t\t\tfromHook,\n\t\t} satisfies CompactionEntry<T>);\n\t}\n\n\tasync appendCustomEntry(customType: string, data?: unknown): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"custom\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tcustomType,\n\t\t\tdata,\n\t\t} satisfies CustomEntry);\n\t}\n\n\tasync appendCustomMessageEntry<T = unknown>(\n\t\tcustomType: string,\n\t\tcontent: string | (TextContent | ImageContent)[],\n\t\tdisplay: boolean,\n\t\tdetails?: T,\n\t): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"custom_message\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tcustomType,\n\t\t\tcontent,\n\t\t\tdisplay,\n\t\t\tdetails,\n\t\t} satisfies CustomMessageEntry<T>);\n\t}\n\n\tasync appendLabel(targetId: string, label: string | undefined): Promise<string> {\n\t\tif (!(await this.storage.getEntry(targetId))) {\n\t\t\tthrow new SessionError(\"not_found\", `Entry ${targetId} not found`);\n\t\t}\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"label\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\ttargetId,\n\t\t\tlabel,\n\t\t} satisfies LabelEntry);\n\t}\n\n\tasync appendSessionName(name: string): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"session_info\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tname: name.trim(),\n\t\t} satisfies SessionInfoEntry);\n\t}\n\n\tasync moveTo(entryId: string | null, summary?: SessionMoveSummary): Promise<string | undefined> {\n\t\tif (entryId !== null && !(await this.storage.getEntry(entryId))) {\n\t\t\tthrow new SessionError(\"not_found\", `Entry ${entryId} not found`);\n\t\t}\n\t\tawait this.storage.setLeafId(entryId);\n\t\tif (!summary) return undefined;\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"branch_summary\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: entryId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tfromId: entryId ?? \"root\",\n\t\t\tsummary: summary.summary,\n\t\t\tdetails: summary.details,\n\t\t\tfromHook: summary.fromHook,\n\t\t} satisfies BranchSummaryEntry);\n\t}\n}\n"]}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/harness/session/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,KAAK,EAQX,cAAc,EAEd,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAEhB,MAAM,aAAa,CAAC;AA0ErB,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,gBAAgB,EAAE,GAAG,cAAc,CAOnF;AAED,qBAAa,OAAO,CAAC,SAAS,SAAS,eAAe,GAAG,eAAe;IACvE,OAAO,CAAC,OAAO,CAA4B;IAE3C,YAAY,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,EAE7C;IAED,WAAW,IAAI,OAAO,CAAC,SAAS,CAAC,CAEhC;IAED,UAAU,IAAI,cAAc,CAAC,SAAS,CAAC,CAEtC;IAED,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAElC;IAED,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAE1D;IAED,UAAU,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAExC;IAEK,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAG5D;IAEK,YAAY,IAAI,OAAO,CAAC,cAAc,CAAC,CAE5C;IAED,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAEhD;IAEK,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAGlD;YAEa,gBAAgB;IAKxB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ1D;IAEK,yBAAyB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQtE;IAEK,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS1E;IAEK,gBAAgB,CAAC,CAAC,GAAG,OAAO,EACjC,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,EACxB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,CAAC,EACX,QAAQ,CAAC,EAAE,OAAO,GAChB,OAAO,CAAC,MAAM,CAAC,CAYjB;IAEK,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAS3E;IAEK,wBAAwB,CAAC,CAAC,GAAG,OAAO,EACzC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GAAG,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,EAChD,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,CAAC,GACT,OAAO,CAAC,MAAM,CAAC,CAWjB;IAEK,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAY9E;IAEK,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQrD;IAEK,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAgB9F;CACD"}
@@ -66,7 +66,6 @@ export function buildSessionContext(pathEntries) {
66
66
  };
67
67
  }
68
68
  export class Session {
69
- storage;
70
69
  constructor(storage) {
71
70
  this.storage = storage;
72
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/harness/session/session.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ImageContent, TextContent } from \"@greppleai/grip-ai\";\nimport type { AgentMessage } from \"../../types.ts\";\nimport { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage } from \"../messages.ts\";\nimport type {\n\tBranchSummaryEntry,\n\tCompactionEntry,\n\tCustomEntry,\n\tCustomMessageEntry,\n\tLabelEntry,\n\tMessageEntry,\n\tModelChangeEntry,\n\tSessionContext,\n\tSessionInfoEntry,\n\tSessionMetadata,\n\tSessionMoveSummary,\n\tSessionStorage,\n\tSessionTreeEntry,\n\tThinkingLevelChangeEntry,\n} from \"../types.ts\";\nimport { SessionError } from \"../types.ts\";\n\ninterface SessionContextBuildState {\n\tthinkingLevel: string;\n\tmodel: SessionContext[\"model\"];\n\tcompaction: CompactionEntry | null;\n}\n\nfunction resolveSessionContextState(pathEntries: SessionTreeEntry[]): SessionContextBuildState {\n\tconst state: SessionContextBuildState = { thinkingLevel: \"off\", model: null, compaction: null };\n\tfor (const entry of pathEntries) {\n\t\tswitch (entry.type) {\n\t\t\tcase \"thinking_level_change\":\n\t\t\t\tstate.thinkingLevel = entry.thinkingLevel;\n\t\t\t\tbreak;\n\t\t\tcase \"model_change\":\n\t\t\t\tstate.model = { provider: entry.provider, modelId: entry.modelId };\n\t\t\t\tbreak;\n\t\t\tcase \"message\":\n\t\t\t\tif (entry.message.role === \"assistant\") {\n\t\t\t\t\tstate.model = { provider: entry.message.provider, modelId: entry.message.model };\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"compaction\":\n\t\t\t\tstate.compaction = entry;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn state;\n}\n\nfunction appendSessionEntryMessage(messages: AgentMessage[], entry: SessionTreeEntry): void {\n\tif (entry.type === \"message\") {\n\t\tmessages.push(entry.message as AgentMessage);\n\t\treturn;\n\t}\n\tif (entry.type === \"custom_message\") {\n\t\tmessages.push(\n\t\t\tcreateCustomMessage(\n\t\t\t\tentry.customType,\n\t\t\t\tentry.content as string | (TextContent | ImageContent)[],\n\t\t\t\tentry.display,\n\t\t\t\tentry.details,\n\t\t\t\tentry.timestamp,\n\t\t\t),\n\t\t);\n\t\treturn;\n\t}\n\tif (entry.type === \"branch_summary\" && entry.summary) {\n\t\tmessages.push(createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp));\n\t}\n}\n\nfunction buildSessionMessages(pathEntries: SessionTreeEntry[], compaction: CompactionEntry | null): AgentMessage[] {\n\tconst messages: AgentMessage[] = [];\n\tif (!compaction) {\n\t\tfor (const entry of pathEntries) appendSessionEntryMessage(messages, entry);\n\t\treturn messages;\n\t}\n\tmessages.push(createCompactionSummaryMessage(compaction.summary, compaction.tokensBefore, compaction.timestamp));\n\tconst compactionIdx = pathEntries.findIndex((entry) => entry.type === \"compaction\" && entry.id === compaction.id);\n\tlet foundFirstKept = false;\n\tfor (let index = 0; index < compactionIdx; index++) {\n\t\tconst entry = pathEntries[index]!;\n\t\tif (entry.id === compaction.firstKeptEntryId) foundFirstKept = true;\n\t\tif (foundFirstKept) appendSessionEntryMessage(messages, entry);\n\t}\n\tfor (let index = compactionIdx + 1; index < pathEntries.length; index++) {\n\t\tappendSessionEntryMessage(messages, pathEntries[index]!);\n\t}\n\treturn messages;\n}\n\nexport function buildSessionContext(pathEntries: SessionTreeEntry[]): SessionContext {\n\tconst state = resolveSessionContextState(pathEntries);\n\treturn {\n\t\tmessages: buildSessionMessages(pathEntries, state.compaction),\n\t\tthinkingLevel: state.thinkingLevel,\n\t\tmodel: state.model,\n\t};\n}\n\nexport class Session<TMetadata extends SessionMetadata = SessionMetadata> {\n\tprivate storage: SessionStorage<TMetadata>;\n\n\tconstructor(storage: SessionStorage<TMetadata>) {\n\t\tthis.storage = storage;\n\t}\n\n\tgetMetadata(): Promise<TMetadata> {\n\t\treturn this.storage.getMetadata();\n\t}\n\n\tgetStorage(): SessionStorage<TMetadata> {\n\t\treturn this.storage;\n\t}\n\n\tgetLeafId(): Promise<string | null> {\n\t\treturn this.storage.getLeafId();\n\t}\n\n\tgetEntry(id: string): Promise<SessionTreeEntry | undefined> {\n\t\treturn this.storage.getEntry(id);\n\t}\n\n\tgetEntries(): Promise<SessionTreeEntry[]> {\n\t\treturn this.storage.getEntries();\n\t}\n\n\tasync getBranch(fromId?: string): Promise<SessionTreeEntry[]> {\n\t\tconst leafId = fromId ?? (await this.storage.getLeafId());\n\t\treturn this.storage.getPathToRoot(leafId);\n\t}\n\n\tasync buildContext(): Promise<SessionContext> {\n\t\treturn buildSessionContext(await this.getBranch());\n\t}\n\n\tgetLabel(id: string): Promise<string | undefined> {\n\t\treturn this.storage.getLabel(id);\n\t}\n\n\tasync getSessionName(): Promise<string | undefined> {\n\t\tconst entries = await this.storage.findEntries(\"session_info\");\n\t\treturn entries[entries.length - 1]?.name?.trim() || undefined;\n\t}\n\n\tprivate async appendTypedEntry<TEntry extends SessionTreeEntry>(entry: TEntry): Promise<string> {\n\t\tawait this.storage.appendEntry(entry);\n\t\treturn entry.id;\n\t}\n\n\tasync appendMessage(message: AgentMessage): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"message\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tmessage,\n\t\t} satisfies MessageEntry);\n\t}\n\n\tasync appendThinkingLevelChange(thinkingLevel: string): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"thinking_level_change\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tthinkingLevel,\n\t\t} satisfies ThinkingLevelChangeEntry);\n\t}\n\n\tasync appendModelChange(provider: string, modelId: string): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"model_change\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tprovider,\n\t\t\tmodelId,\n\t\t} satisfies ModelChangeEntry);\n\t}\n\n\tasync appendCompaction<T = unknown>(\n\t\tsummary: string,\n\t\tfirstKeptEntryId: string,\n\t\ttokensBefore: number,\n\t\tdetails?: T,\n\t\tfromHook?: boolean,\n\t): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"compaction\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tsummary,\n\t\t\tfirstKeptEntryId,\n\t\t\ttokensBefore,\n\t\t\tdetails,\n\t\t\tfromHook,\n\t\t} satisfies CompactionEntry<T>);\n\t}\n\n\tasync appendCustomEntry(customType: string, data?: unknown): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"custom\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tcustomType,\n\t\t\tdata,\n\t\t} satisfies CustomEntry);\n\t}\n\n\tasync appendCustomMessageEntry<T = unknown>(\n\t\tcustomType: string,\n\t\tcontent: string | (TextContent | ImageContent)[],\n\t\tdisplay: boolean,\n\t\tdetails?: T,\n\t): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"custom_message\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tcustomType,\n\t\t\tcontent,\n\t\t\tdisplay,\n\t\t\tdetails,\n\t\t} satisfies CustomMessageEntry<T>);\n\t}\n\n\tasync appendLabel(targetId: string, label: string | undefined): Promise<string> {\n\t\tif (!(await this.storage.getEntry(targetId))) {\n\t\t\tthrow new SessionError(\"not_found\", `Entry ${targetId} not found`);\n\t\t}\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"label\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\ttargetId,\n\t\t\tlabel,\n\t\t} satisfies LabelEntry);\n\t}\n\n\tasync appendSessionName(name: string): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"session_info\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tname: name.trim(),\n\t\t} satisfies SessionInfoEntry);\n\t}\n\n\tasync moveTo(entryId: string | null, summary?: SessionMoveSummary): Promise<string | undefined> {\n\t\tif (entryId !== null && !(await this.storage.getEntry(entryId))) {\n\t\t\tthrow new SessionError(\"not_found\", `Entry ${entryId} not found`);\n\t\t}\n\t\tawait this.storage.setLeafId(entryId);\n\t\tif (!summary) return undefined;\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"branch_summary\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: entryId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tfromId: entryId ?? \"root\",\n\t\t\tsummary: summary.summary,\n\t\t\tdetails: summary.details,\n\t\t\tfromHook: summary.fromHook,\n\t\t} satisfies BranchSummaryEntry);\n\t}\n}\n"]}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/harness/session/session.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ImageContent, TextContent } from \"@greppleai/grip-ai\";\nimport type { AgentMessage } from \"../../types.ts\";\nimport { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage } from \"../messages.ts\";\nimport type {\n\tBranchSummaryEntry,\n\tCompactionEntry,\n\tCustomEntry,\n\tCustomMessageEntry,\n\tLabelEntry,\n\tMessageEntry,\n\tModelChangeEntry,\n\tSessionContext,\n\tSessionInfoEntry,\n\tSessionMetadata,\n\tSessionMoveSummary,\n\tSessionStorage,\n\tSessionTreeEntry,\n\tThinkingLevelChangeEntry,\n} from \"../types.ts\";\nimport { SessionError } from \"../types.ts\";\n\ninterface SessionContextBuildState {\n\tthinkingLevel: string;\n\tmodel: SessionContext[\"model\"];\n\tcompaction: CompactionEntry | null;\n}\n\nfunction resolveSessionContextState(pathEntries: SessionTreeEntry[]): SessionContextBuildState {\n\tconst state: SessionContextBuildState = { thinkingLevel: \"off\", model: null, compaction: null };\n\tfor (const entry of pathEntries) {\n\t\tswitch (entry.type) {\n\t\t\tcase \"thinking_level_change\":\n\t\t\t\tstate.thinkingLevel = entry.thinkingLevel;\n\t\t\t\tbreak;\n\t\t\tcase \"model_change\":\n\t\t\t\tstate.model = { provider: entry.provider, modelId: entry.modelId };\n\t\t\t\tbreak;\n\t\t\tcase \"message\":\n\t\t\t\tif (entry.message.role === \"assistant\") {\n\t\t\t\t\tstate.model = { provider: entry.message.provider, modelId: entry.message.model };\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"compaction\":\n\t\t\t\tstate.compaction = entry;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn state;\n}\n\nfunction appendSessionEntryMessage(messages: AgentMessage[], entry: SessionTreeEntry): void {\n\tif (entry.type === \"message\") {\n\t\tmessages.push(entry.message as AgentMessage);\n\t\treturn;\n\t}\n\tif (entry.type === \"custom_message\") {\n\t\tmessages.push(\n\t\t\tcreateCustomMessage(\n\t\t\t\tentry.customType,\n\t\t\t\tentry.content as string | (TextContent | ImageContent)[],\n\t\t\t\tentry.display,\n\t\t\t\tentry.details,\n\t\t\t\tentry.timestamp,\n\t\t\t),\n\t\t);\n\t\treturn;\n\t}\n\tif (entry.type === \"branch_summary\" && entry.summary) {\n\t\tmessages.push(createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp));\n\t}\n}\n\nfunction buildSessionMessages(pathEntries: SessionTreeEntry[], compaction: CompactionEntry | null): AgentMessage[] {\n\tconst messages: AgentMessage[] = [];\n\tif (!compaction) {\n\t\tfor (const entry of pathEntries) appendSessionEntryMessage(messages, entry);\n\t\treturn messages;\n\t}\n\tmessages.push(createCompactionSummaryMessage(compaction.summary, compaction.tokensBefore, compaction.timestamp));\n\tconst compactionIdx = pathEntries.findIndex((entry) => entry.type === \"compaction\" && entry.id === compaction.id);\n\tlet foundFirstKept = false;\n\tfor (let index = 0; index < compactionIdx; index++) {\n\t\tconst entry = pathEntries[index]!;\n\t\tif (entry.id === compaction.firstKeptEntryId) foundFirstKept = true;\n\t\tif (foundFirstKept) appendSessionEntryMessage(messages, entry);\n\t}\n\tfor (let index = compactionIdx + 1; index < pathEntries.length; index++) {\n\t\tappendSessionEntryMessage(messages, pathEntries[index]!);\n\t}\n\treturn messages;\n}\n\nexport function buildSessionContext(pathEntries: SessionTreeEntry[]): SessionContext {\n\tconst state = resolveSessionContextState(pathEntries);\n\treturn {\n\t\tmessages: buildSessionMessages(pathEntries, state.compaction),\n\t\tthinkingLevel: state.thinkingLevel,\n\t\tmodel: state.model,\n\t};\n}\n\nexport class Session<TMetadata extends SessionMetadata = SessionMetadata> {\n\tprivate storage: SessionStorage<TMetadata>;\n\n\tconstructor(storage: SessionStorage<TMetadata>) {\n\t\tthis.storage = storage;\n\t}\n\n\tgetMetadata(): Promise<TMetadata> {\n\t\treturn this.storage.getMetadata();\n\t}\n\n\tgetStorage(): SessionStorage<TMetadata> {\n\t\treturn this.storage;\n\t}\n\n\tgetLeafId(): Promise<string | null> {\n\t\treturn this.storage.getLeafId();\n\t}\n\n\tgetEntry(id: string): Promise<SessionTreeEntry | undefined> {\n\t\treturn this.storage.getEntry(id);\n\t}\n\n\tgetEntries(): Promise<SessionTreeEntry[]> {\n\t\treturn this.storage.getEntries();\n\t}\n\n\tasync getBranch(fromId?: string): Promise<SessionTreeEntry[]> {\n\t\tconst leafId = fromId ?? (await this.storage.getLeafId());\n\t\treturn this.storage.getPathToRoot(leafId);\n\t}\n\n\tasync buildContext(): Promise<SessionContext> {\n\t\treturn buildSessionContext(await this.getBranch());\n\t}\n\n\tgetLabel(id: string): Promise<string | undefined> {\n\t\treturn this.storage.getLabel(id);\n\t}\n\n\tasync getSessionName(): Promise<string | undefined> {\n\t\tconst entries = await this.storage.findEntries(\"session_info\");\n\t\treturn entries[entries.length - 1]?.name?.trim() || undefined;\n\t}\n\n\tprivate async appendTypedEntry<TEntry extends SessionTreeEntry>(entry: TEntry): Promise<string> {\n\t\tawait this.storage.appendEntry(entry);\n\t\treturn entry.id;\n\t}\n\n\tasync appendMessage(message: AgentMessage): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"message\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tmessage,\n\t\t} satisfies MessageEntry);\n\t}\n\n\tasync appendThinkingLevelChange(thinkingLevel: string): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"thinking_level_change\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tthinkingLevel,\n\t\t} satisfies ThinkingLevelChangeEntry);\n\t}\n\n\tasync appendModelChange(provider: string, modelId: string): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"model_change\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tprovider,\n\t\t\tmodelId,\n\t\t} satisfies ModelChangeEntry);\n\t}\n\n\tasync appendCompaction<T = unknown>(\n\t\tsummary: string,\n\t\tfirstKeptEntryId: string,\n\t\ttokensBefore: number,\n\t\tdetails?: T,\n\t\tfromHook?: boolean,\n\t): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"compaction\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tsummary,\n\t\t\tfirstKeptEntryId,\n\t\t\ttokensBefore,\n\t\t\tdetails,\n\t\t\tfromHook,\n\t\t} satisfies CompactionEntry<T>);\n\t}\n\n\tasync appendCustomEntry(customType: string, data?: unknown): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"custom\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tcustomType,\n\t\t\tdata,\n\t\t} satisfies CustomEntry);\n\t}\n\n\tasync appendCustomMessageEntry<T = unknown>(\n\t\tcustomType: string,\n\t\tcontent: string | (TextContent | ImageContent)[],\n\t\tdisplay: boolean,\n\t\tdetails?: T,\n\t): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"custom_message\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tcustomType,\n\t\t\tcontent,\n\t\t\tdisplay,\n\t\t\tdetails,\n\t\t} satisfies CustomMessageEntry<T>);\n\t}\n\n\tasync appendLabel(targetId: string, label: string | undefined): Promise<string> {\n\t\tif (!(await this.storage.getEntry(targetId))) {\n\t\t\tthrow new SessionError(\"not_found\", `Entry ${targetId} not found`);\n\t\t}\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"label\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\ttargetId,\n\t\t\tlabel,\n\t\t} satisfies LabelEntry);\n\t}\n\n\tasync appendSessionName(name: string): Promise<string> {\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"session_info\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: await this.storage.getLeafId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tname: name.trim(),\n\t\t} satisfies SessionInfoEntry);\n\t}\n\n\tasync moveTo(entryId: string | null, summary?: SessionMoveSummary): Promise<string | undefined> {\n\t\tif (entryId !== null && !(await this.storage.getEntry(entryId))) {\n\t\t\tthrow new SessionError(\"not_found\", `Entry ${entryId} not found`);\n\t\t}\n\t\tawait this.storage.setLeafId(entryId);\n\t\tif (!summary) return undefined;\n\t\treturn this.appendTypedEntry({\n\t\t\ttype: \"branch_summary\",\n\t\t\tid: await this.storage.createEntryId(),\n\t\t\tparentId: entryId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tfromId: entryId ?? \"root\",\n\t\t\tsummary: summary.summary,\n\t\t\tdetails: summary.details,\n\t\t\tfromHook: summary.fromHook,\n\t\t} satisfies BranchSummaryEntry);\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../../../src/harness/session/uuid.ts"],"names":[],"mappings":"AAcA,wBAAgB,MAAM,IAAI,MAAM,CAkC/B","sourcesContent":["let lastTimestamp = -Infinity;\nlet sequence = 0;\n\nfunction fillRandomBytes(bytes: Uint8Array): void {\n\tconst crypto = globalThis.crypto;\n\tif (crypto?.getRandomValues) {\n\t\tcrypto.getRandomValues(bytes);\n\t\treturn;\n\t}\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tbytes[i] = Math.floor(Math.random() * 256);\n\t}\n}\n\nexport function uuidv7(): string {\n\tconst random = new Uint8Array(16);\n\tfillRandomBytes(random);\n\tconst timestamp = Date.now();\n\n\tif (timestamp > lastTimestamp) {\n\t\tsequence = random[6] * 0x1000000 + random[7] * 0x10000 + random[8] * 0x100 + random[9];\n\t\tlastTimestamp = timestamp;\n\t} else {\n\t\tsequence = (sequence + 1) >>> 0;\n\t\tif (sequence === 0) {\n\t\t\tlastTimestamp++;\n\t\t}\n\t}\n\n\tconst bytes = new Uint8Array(16);\n\tbytes[0] = (lastTimestamp / 0x10000000000) & 0xff;\n\tbytes[1] = (lastTimestamp / 0x100000000) & 0xff;\n\tbytes[2] = (lastTimestamp / 0x1000000) & 0xff;\n\tbytes[3] = (lastTimestamp / 0x10000) & 0xff;\n\tbytes[4] = (lastTimestamp / 0x100) & 0xff;\n\tbytes[5] = lastTimestamp & 0xff;\n\tbytes[6] = 0x70 | ((sequence >>> 28) & 0x0f);\n\tbytes[7] = (sequence >>> 20) & 0xff;\n\tbytes[8] = 0x80 | ((sequence >>> 14) & 0x3f);\n\tbytes[9] = (sequence >>> 6) & 0xff;\n\tbytes[10] = ((sequence & 0x3f) << 2) | (random[10] & 0x03);\n\tbytes[11] = random[11];\n\tbytes[12] = random[12];\n\tbytes[13] = random[13];\n\tbytes[14] = random[14];\n\tbytes[15] = random[15];\n\n\treturn formatUuid(bytes);\n}\n\nfunction formatUuid(bytes: Uint8Array): string {\n\tconst hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\"));\n\treturn `${hex.slice(0, 4).join(\"\")}-${hex.slice(4, 6).join(\"\")}-${hex.slice(6, 8).join(\"\")}-${hex.slice(8, 10).join(\"\")}-${hex.slice(10, 16).join(\"\")}`;\n}\n"]}
1
+ {"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../../../src/harness/session/uuid.ts"],"names":[],"mappings":"AAcA,wBAAgB,MAAM,IAAI,MAAM,CAkC/B"}
@@ -1 +1 @@
1
- {"version":3,"file":"uuid.js","sourceRoot":"","sources":["../../../src/harness/session/uuid.ts"],"names":[],"mappings":"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","sourcesContent":["let lastTimestamp = -Infinity;\nlet sequence = 0;\n\nfunction fillRandomBytes(bytes: Uint8Array): void {\n\tconst crypto = globalThis.crypto;\n\tif (crypto?.getRandomValues) {\n\t\tcrypto.getRandomValues(bytes);\n\t\treturn;\n\t}\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tbytes[i] = Math.floor(Math.random() * 256);\n\t}\n}\n\nexport function uuidv7(): string {\n\tconst random = new Uint8Array(16);\n\tfillRandomBytes(random);\n\tconst timestamp = Date.now();\n\n\tif (timestamp > lastTimestamp) {\n\t\tsequence = random[6] * 0x1000000 + random[7] * 0x10000 + random[8] * 0x100 + random[9];\n\t\tlastTimestamp = timestamp;\n\t} else {\n\t\tsequence = (sequence + 1) >>> 0;\n\t\tif (sequence === 0) {\n\t\t\tlastTimestamp++;\n\t\t}\n\t}\n\n\tconst bytes = new Uint8Array(16);\n\tbytes[0] = (lastTimestamp / 0x10000000000) & 0xff;\n\tbytes[1] = (lastTimestamp / 0x100000000) & 0xff;\n\tbytes[2] = (lastTimestamp / 0x1000000) & 0xff;\n\tbytes[3] = (lastTimestamp / 0x10000) & 0xff;\n\tbytes[4] = (lastTimestamp / 0x100) & 0xff;\n\tbytes[5] = lastTimestamp & 0xff;\n\tbytes[6] = 0x70 | ((sequence >>> 28) & 0x0f);\n\tbytes[7] = (sequence >>> 20) & 0xff;\n\tbytes[8] = 0x80 | ((sequence >>> 14) & 0x3f);\n\tbytes[9] = (sequence >>> 6) & 0xff;\n\tbytes[10] = ((sequence & 0x3f) << 2) | (random[10] & 0x03);\n\tbytes[11] = random[11];\n\tbytes[12] = random[12];\n\tbytes[13] = random[13];\n\tbytes[14] = random[14];\n\tbytes[15] = random[15];\n\n\treturn formatUuid(bytes);\n}\n\nfunction formatUuid(bytes: Uint8Array): string {\n\tconst hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\"));\n\treturn `${hex.slice(0, 4).join(\"\")}-${hex.slice(4, 6).join(\"\")}-${hex.slice(6, 8).join(\"\")}-${hex.slice(8, 10).join(\"\")}-${hex.slice(10, 16).join(\"\")}`;\n}\n"]}
1
+ {"version":3,"file":"uuid.js","sourceRoot":"","sources":["../../../src/harness/session/uuid.ts"],"names":[],"mappings":"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","sourcesContent":["let lastTimestamp = -Infinity;\nlet sequence = 0;\n\nfunction fillRandomBytes(bytes: Uint8Array<ArrayBuffer>): void {\n\tconst crypto = globalThis.crypto;\n\tif (crypto?.getRandomValues) {\n\t\tcrypto.getRandomValues(bytes);\n\t\treturn;\n\t}\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tbytes[i] = Math.floor(Math.random() * 256);\n\t}\n}\n\nexport function uuidv7(): string {\n\tconst random = new Uint8Array(16);\n\tfillRandomBytes(random);\n\tconst timestamp = Date.now();\n\n\tif (timestamp > lastTimestamp) {\n\t\tsequence = random[6] * 0x1000000 + random[7] * 0x10000 + random[8] * 0x100 + random[9];\n\t\tlastTimestamp = timestamp;\n\t} else {\n\t\tsequence = (sequence + 1) >>> 0;\n\t\tif (sequence === 0) {\n\t\t\tlastTimestamp++;\n\t\t}\n\t}\n\n\tconst bytes = new Uint8Array(16);\n\tbytes[0] = (lastTimestamp / 0x10000000000) & 0xff;\n\tbytes[1] = (lastTimestamp / 0x100000000) & 0xff;\n\tbytes[2] = (lastTimestamp / 0x1000000) & 0xff;\n\tbytes[3] = (lastTimestamp / 0x10000) & 0xff;\n\tbytes[4] = (lastTimestamp / 0x100) & 0xff;\n\tbytes[5] = lastTimestamp & 0xff;\n\tbytes[6] = 0x70 | ((sequence >>> 28) & 0x0f);\n\tbytes[7] = (sequence >>> 20) & 0xff;\n\tbytes[8] = 0x80 | ((sequence >>> 14) & 0x3f);\n\tbytes[9] = (sequence >>> 6) & 0xff;\n\tbytes[10] = ((sequence & 0x3f) << 2) | (random[10] & 0x03);\n\tbytes[11] = random[11];\n\tbytes[12] = random[12];\n\tbytes[13] = random[13];\n\tbytes[14] = random[14];\n\tbytes[15] = random[15];\n\n\treturn formatUuid(bytes);\n}\n\nfunction formatUuid(bytes: Uint8Array): string {\n\tconst hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\"));\n\treturn `${hex.slice(0, 4).join(\"\")}-${hex.slice(4, 6).join(\"\")}-${hex.slice(6, 8).join(\"\")}-${hex.slice(8, 10).join(\"\")}-${hex.slice(10, 16).join(\"\")}`;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/harness/skills.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAA8C,KAAK,KAAK,EAAW,MAAM,YAAY,CAAC;AAOhH,MAAM,MAAM,mBAAmB,GAC5B,kBAAkB,GAClB,aAAa,GACb,aAAa,GACb,cAAc,GACd,kBAAkB,CAAC;AAEtB,6CAA6C;AAC7C,MAAM,WAAW,eAAe;IAC/B,gEAAgE;IAChE,IAAI,EAAE,SAAS,CAAC;IAChB,8BAA8B;IAC9B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;CACb;AAcD,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,WAAW,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,kEAAkE;AAClE,MAAM,MAAM,iBAAiB,CAAC,OAAO,IAAI;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,8DAA8D;AAC9D,MAAM,WAAW,YAAY,CAAC,MAAM,SAAS,KAAK,EAAE,OAAO;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;CAChB;AAED,kEAAkE;AAClE,MAAM,WAAW,sBAAsB,CAAC,OAAO,CAAE,SAAQ,eAAe;IACvE,MAAM,EAAE,OAAO,CAAC;CAChB;AAED,mEAAmE;AACnE,MAAM,WAAW,uBAAuB,CAAC,MAAM,SAAS,KAAK,EAAE,OAAO;IACrE,MAAM,EAAE,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACxC,WAAW,EAAE,sBAAsB,CAAC,OAAO,CAAC,EAAE,CAAC;CAC/C;AAYD,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,KAAK,EAAE,sBAAsB,CAAC,EAAE,MAAM,GAAG,MAAM,CAG3F;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuBtG;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,SAAS,KAAK,GAAG,KAAK,EAC5E,GAAG,EAAE,YAAY,EACjB,MAAM,EAAE,iBAAiB,CAAC,OAAO,CAAC,EAAE,EACpC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,KAAK,MAAM,GAClD,OAAO,CAAC,uBAAuB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAWnD","sourcesContent":["import ignore from \"ignore\";\nimport { parse } from \"yaml\";\nimport { type ExecutionEnv, type FileError, type FileInfo, type Result, type Skill, toError } from \"./types.ts\";\n\nconst MAX_NAME_LENGTH = 64;\nconst MAX_DESCRIPTION_LENGTH = 1024;\nconst IGNORE_FILE_NAMES = [\".gitignore\", \".ignore\", \".fdignore\"];\ntype SkillPathKind = \"file\" | \"directory\";\n\nexport type SkillDiagnosticCode =\n\t| \"file_info_failed\"\n\t| \"list_failed\"\n\t| \"read_failed\"\n\t| \"parse_failed\"\n\t| \"invalid_metadata\";\n\n/** Warning produced while loading skills. */\nexport interface SkillDiagnostic {\n\t/** Diagnostic severity. Currently only warnings are emitted. */\n\ttype: \"warning\";\n\t/** Stable diagnostic code. */\n\tcode: SkillDiagnosticCode;\n\t/** Human-readable diagnostic message. */\n\tmessage: string;\n\t/** Path associated with the diagnostic. */\n\tpath: string;\n}\n\nfunction appendFileInfoDiagnostic(diagnostics: SkillDiagnostic[], error: FileError, path: string): void {\n\tif (error.code === \"not_found\") return;\n\tdiagnostics.push({ type: \"warning\", code: \"file_info_failed\", message: error.message, path });\n}\n\ninterface SkillFrontmatter {\n\tname?: string;\n\tdescription?: string;\n\t\"disable-model-invocation\"?: boolean;\n\t[key: string]: unknown;\n}\n\n/** Skills and warnings produced by a directory load. */\nexport interface LoadSkillsResult {\n\tskills: Skill[];\n\tdiagnostics: SkillDiagnostic[];\n}\n\n/** Source-tagged directory passed to the sourced skill loader. */\nexport type SourcedSkillInput<TSource> = {\n\tpath: string;\n\tsource: TSource;\n};\n\n/** Loaded skill paired with its caller-defined provenance. */\nexport interface SourcedSkill<TSkill extends Skill, TSource> {\n\tskill: TSkill;\n\tsource: TSource;\n}\n\n/** Skill diagnostic paired with its caller-defined provenance. */\nexport interface SourcedSkillDiagnostic<TSource> extends SkillDiagnostic {\n\tsource: TSource;\n}\n\n/** Skills and diagnostics produced by a sourced directory load. */\nexport interface LoadSourcedSkillsResult<TSkill extends Skill, TSource> {\n\tskills: SourcedSkill<TSkill, TSource>[];\n\tdiagnostics: SourcedSkillDiagnostic<TSource>[];\n}\n\ninterface SkillFileLoadResult {\n\tskill: Skill | null;\n\tdiagnostics: SkillDiagnostic[];\n}\n\ntype ParsedFrontmatter<T> = {\n\tfrontmatter: T;\n\tbody: string;\n};\n\n/** Format a skill invocation prompt, optionally appending additional user instructions. */\nexport function formatSkillInvocation(skill: Skill, additionalInstructions?: string): string {\n\tconst skillBlock = `<skill name=\"${skill.name}\" location=\"${skill.filePath}\">\\nReferences are relative to ${dirnameEnvPath(skill.filePath)}.\\n\\n${skill.content}\\n</skill>`;\n\treturn additionalInstructions ? `${skillBlock}\\n\\n${additionalInstructions}` : skillBlock;\n}\n\n/**\n * Load skills from one or more directories.\n *\n * Traverses directories recursively, loads `SKILL.md` files, loads direct root `.md` files as skills, honors ignore files,\n * and returns diagnostics for invalid skill files. Missing input directories are skipped.\n */\nexport async function loadSkills(env: ExecutionEnv, dirs: string | string[]): Promise<LoadSkillsResult> {\n\tconst skills: Skill[] = [];\n\tconst diagnostics: SkillDiagnostic[] = [];\n\tfor (const dir of Array.isArray(dirs) ? dirs : [dirs]) {\n\t\tconst rootInfoResult = await env.fileInfo(dir);\n\t\tif (!rootInfoResult.ok) {\n\t\t\tif (rootInfoResult.error.code !== \"not_found\") {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\ttype: \"warning\",\n\t\t\t\t\tcode: \"file_info_failed\",\n\t\t\t\t\tmessage: rootInfoResult.error.message,\n\t\t\t\t\tpath: dir,\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tconst rootInfo = rootInfoResult.value;\n\t\tif ((await resolveKind(env, rootInfo, diagnostics)) !== \"directory\") continue;\n\t\tconst result = await loadSkillsFromDirInternal(env, rootInfo.path, true, ignore(), rootInfo.path);\n\t\tskills.push(...result.skills);\n\t\tdiagnostics.push(...result.diagnostics);\n\t}\n\treturn { skills, diagnostics };\n}\n\n/**\n * Load skills from source-tagged directories.\n *\n * Source values are preserved exactly and attached to every loaded skill and diagnostic. The agent package does not\n * interpret source values; applications define their own provenance shape.\n */\nexport async function loadSourcedSkills<TSource, TSkill extends Skill = Skill>(\n\tenv: ExecutionEnv,\n\tinputs: SourcedSkillInput<TSource>[],\n\tmapSkill?: (skill: Skill, source: TSource) => TSkill,\n): Promise<LoadSourcedSkillsResult<TSkill, TSource>> {\n\tconst skills: SourcedSkill<TSkill, TSource>[] = [];\n\tconst diagnostics: SourcedSkillDiagnostic<TSource>[] = [];\n\tfor (const input of inputs) {\n\t\tconst result = await loadSkills(env, input.path);\n\t\tfor (const skill of result.skills) {\n\t\t\tskills.push({ skill: mapSkill ? mapSkill(skill, input.source) : (skill as TSkill), source: input.source });\n\t\t}\n\t\tfor (const diagnostic of result.diagnostics) diagnostics.push({ ...diagnostic, source: input.source });\n\t}\n\treturn { skills, diagnostics };\n}\n\nasync function findDirectorySkill(\n\tenv: ExecutionEnv,\n\tentries: FileInfo[],\n\tignoreMatcher: ignore.Ignore,\n\trootDir: string,\n\tdiagnostics: SkillDiagnostic[],\n): Promise<SkillFileLoadResult | undefined> {\n\tfor (const entry of entries) {\n\t\tif (entry.name !== \"SKILL.md\") continue;\n\t\tif ((await resolveKind(env, entry, diagnostics)) !== \"file\") continue;\n\t\tif (ignoreMatcher.ignores(relativeEnvPath(rootDir, entry.path))) continue;\n\t\treturn loadSkillFromFile(env, entry.path);\n\t}\n\treturn undefined;\n}\n\nfunction shouldSkipChildSkillEntry(entry: FileInfo): boolean {\n\treturn entry.name.startsWith(\".\") || entry.name === \"node_modules\";\n}\n\nasync function loadChildSkillEntry(\n\tenv: ExecutionEnv,\n\tentry: FileInfo,\n\tincludeRootFiles: boolean,\n\tignoreMatcher: ignore.Ignore,\n\trootDir: string,\n\tdiagnostics: SkillDiagnostic[],\n): Promise<LoadSkillsResult> {\n\tif (shouldSkipChildSkillEntry(entry)) return { skills: [], diagnostics: [] };\n\tconst kind = await resolveKind(env, entry, diagnostics);\n\tif (!kind) return { skills: [], diagnostics: [] };\n\tconst relPath = relativeEnvPath(rootDir, entry.path);\n\tconst ignorePath = kind === \"directory\" ? `${relPath}/` : relPath;\n\tif (ignoreMatcher.ignores(ignorePath)) return { skills: [], diagnostics: [] };\n\tif (kind === \"directory\") return loadSkillsFromDirInternal(env, entry.path, false, ignoreMatcher, rootDir);\n\tif (!includeRootFiles || !entry.name.endsWith(\".md\")) return { skills: [], diagnostics: [] };\n\tconst result = await loadSkillFromFile(env, entry.path);\n\treturn { skills: result.skill ? [result.skill] : [], diagnostics: result.diagnostics };\n}\n\nfunction mergeSkillsResult(target: LoadSkillsResult, source: LoadSkillsResult): void {\n\ttarget.skills.push(...source.skills);\n\ttarget.diagnostics.push(...source.diagnostics);\n}\n\nasync function loadSkillsFromDirInternal(\n\tenv: ExecutionEnv,\n\tdir: string,\n\tincludeRootFiles: boolean,\n\tignoreMatcher: ignore.Ignore,\n\trootDir: string,\n): Promise<LoadSkillsResult> {\n\tconst result: LoadSkillsResult = { skills: [], diagnostics: [] };\n\tconst dirInfoResult = await env.fileInfo(dir);\n\tif (!dirInfoResult.ok) {\n\t\tappendFileInfoDiagnostic(result.diagnostics, dirInfoResult.error, dir);\n\t\treturn result;\n\t}\n\tif ((await resolveKind(env, dirInfoResult.value, result.diagnostics)) !== \"directory\") return result;\n\n\tawait addIgnoreRules(env, ignoreMatcher, dir, rootDir, result.diagnostics);\n\tconst entriesResult = await env.listDir(dir);\n\tif (!entriesResult.ok) {\n\t\tresult.diagnostics.push({\n\t\t\ttype: \"warning\",\n\t\t\tcode: \"list_failed\",\n\t\t\tmessage: entriesResult.error.message,\n\t\t\tpath: dir,\n\t\t});\n\t\treturn result;\n\t}\n\tconst entries = entriesResult.value;\n\tconst directorySkill = await findDirectorySkill(env, entries, ignoreMatcher, rootDir, result.diagnostics);\n\tif (directorySkill) {\n\t\tif (directorySkill.skill) result.skills.push(directorySkill.skill);\n\t\tresult.diagnostics.push(...directorySkill.diagnostics);\n\t\treturn result;\n\t}\n\n\tfor (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {\n\t\tmergeSkillsResult(\n\t\t\tresult,\n\t\t\tawait loadChildSkillEntry(env, entry, includeRootFiles, ignoreMatcher, rootDir, result.diagnostics),\n\t\t);\n\t}\n\treturn result;\n}\n\nasync function addIgnoreRules(\n\tenv: ExecutionEnv,\n\tig: ignore.Ignore,\n\tdir: string,\n\trootDir: string,\n\tdiagnostics: SkillDiagnostic[],\n): Promise<void> {\n\tconst relativeDir = relativeEnvPath(rootDir, dir);\n\tconst prefix = relativeDir ? `${relativeDir}/` : \"\";\n\n\tfor (const filename of IGNORE_FILE_NAMES) {\n\t\tconst ignorePath = joinEnvPath(dir, filename);\n\t\tconst info = await env.fileInfo(ignorePath);\n\t\tif (!info.ok) {\n\t\t\tif (info.error.code !== \"not_found\") {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\ttype: \"warning\",\n\t\t\t\t\tcode: \"file_info_failed\",\n\t\t\t\t\tmessage: info.error.message,\n\t\t\t\t\tpath: ignorePath,\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (info.value.kind !== \"file\") continue;\n\t\tconst content = await env.readTextFile(ignorePath);\n\t\tif (!content.ok) {\n\t\t\tdiagnostics.push({ type: \"warning\", code: \"read_failed\", message: content.error.message, path: ignorePath });\n\t\t\tcontinue;\n\t\t}\n\t\tconst patterns = content.value\n\t\t\t.split(/\\r?\\n/)\n\t\t\t.map((line) => prefixIgnorePattern(line, prefix))\n\t\t\t.filter((line): line is string => Boolean(line));\n\t\tif (patterns.length > 0) ig.add(patterns);\n\t}\n}\n\nfunction prefixIgnorePattern(line: string, prefix: string): string | null {\n\tconst trimmed = line.trim();\n\tif (!trimmed) return null;\n\tif (trimmed.startsWith(\"#\") && !trimmed.startsWith(\"\\\\#\")) return null;\n\n\tlet pattern = line;\n\tlet negated = false;\n\tif (pattern.startsWith(\"!\")) {\n\t\tnegated = true;\n\t\tpattern = pattern.slice(1);\n\t} else if (pattern.startsWith(\"\\\\!\")) {\n\t\tpattern = pattern.slice(1);\n\t}\n\tif (pattern.startsWith(\"/\")) pattern = pattern.slice(1);\n\tconst prefixed = prefix ? `${prefix}${pattern}` : pattern;\n\treturn negated ? `!${prefixed}` : prefixed;\n}\n\nasync function loadSkillFromFile(env: ExecutionEnv, filePath: string): Promise<SkillFileLoadResult> {\n\tconst diagnostics: SkillDiagnostic[] = [];\n\tconst rawContent = await env.readTextFile(filePath);\n\tif (!rawContent.ok) {\n\t\tdiagnostics.push({ type: \"warning\", code: \"read_failed\", message: rawContent.error.message, path: filePath });\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\tconst parsed = parseFrontmatter<SkillFrontmatter>(rawContent.value);\n\tif (!parsed.ok) {\n\t\tdiagnostics.push({ type: \"warning\", code: \"parse_failed\", message: parsed.error.message, path: filePath });\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\tconst { frontmatter, body } = parsed.value;\n\tconst skillDir = dirnameEnvPath(filePath);\n\tconst parentDirName = basenameEnvPath(skillDir);\n\tconst description = typeof frontmatter.description === \"string\" ? frontmatter.description : undefined;\n\n\tfor (const error of validateDescription(description)) {\n\t\tdiagnostics.push({ type: \"warning\", code: \"invalid_metadata\", message: error, path: filePath });\n\t}\n\n\tconst frontmatterName = typeof frontmatter.name === \"string\" ? frontmatter.name : undefined;\n\tconst name = frontmatterName || parentDirName;\n\tfor (const error of validateName(name, parentDirName)) {\n\t\tdiagnostics.push({ type: \"warning\", code: \"invalid_metadata\", message: error, path: filePath });\n\t}\n\n\tif (!description || description.trim() === \"\") {\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\treturn {\n\t\tskill: {\n\t\t\tname,\n\t\t\tdescription,\n\t\t\tcontent: body,\n\t\t\tfilePath,\n\t\t\tdisableModelInvocation: frontmatter[\"disable-model-invocation\"] === true,\n\t\t},\n\t\tdiagnostics,\n\t};\n}\n\nfunction validateName(name: string, parentDirName: string): string[] {\n\tconst errors: string[] = [];\n\tif (name !== parentDirName) errors.push(`name \"${name}\" does not match parent directory \"${parentDirName}\"`);\n\tif (name.length > MAX_NAME_LENGTH) errors.push(`name exceeds ${MAX_NAME_LENGTH} characters (${name.length})`);\n\tif (!/^[a-z0-9-]+$/.test(name)) {\n\t\terrors.push(\"name contains invalid characters (must be lowercase a-z, 0-9, hyphens only)\");\n\t}\n\tif (name.startsWith(\"-\") || name.endsWith(\"-\")) errors.push(\"name must not start or end with a hyphen\");\n\tif (name.includes(\"--\")) errors.push(\"name must not contain consecutive hyphens\");\n\treturn errors;\n}\n\nfunction validateDescription(description: string | undefined): string[] {\n\tconst errors: string[] = [];\n\tif (!description || description.trim() === \"\") {\n\t\terrors.push(\"description is required\");\n\t} else if (description.length > MAX_DESCRIPTION_LENGTH) {\n\t\terrors.push(`description exceeds ${MAX_DESCRIPTION_LENGTH} characters (${description.length})`);\n\t}\n\treturn errors;\n}\n\nfunction parseFrontmatter<T extends Record<string, unknown>>(content: string): Result<ParsedFrontmatter<T>, Error> {\n\ttry {\n\t\tconst normalized = content.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\t\tif (!normalized.startsWith(\"---\")) return { ok: true, value: { frontmatter: {} as T, body: normalized } };\n\t\tconst endIndex = normalized.indexOf(\"\\n---\", 3);\n\t\tif (endIndex === -1) return { ok: true, value: { frontmatter: {} as T, body: normalized } };\n\t\tconst yamlString = normalized.slice(4, endIndex);\n\t\tconst body = normalized.slice(endIndex + 4).trim();\n\t\treturn { ok: true, value: { frontmatter: (parse(yamlString) ?? {}) as T, body } };\n\t} catch (error) {\n\t\treturn { ok: false, error: toError(error) };\n\t}\n}\n\nasync function resolveKind(\n\tenv: ExecutionEnv,\n\tinfo: FileInfo,\n\tdiagnostics: SkillDiagnostic[],\n): Promise<SkillPathKind | undefined> {\n\tif (info.kind === \"file\" || info.kind === \"directory\") return info.kind;\n\tconst canonicalPath = await env.canonicalPath(info.path);\n\tif (!canonicalPath.ok) {\n\t\tif (canonicalPath.error.code !== \"not_found\") {\n\t\t\tdiagnostics.push({\n\t\t\t\ttype: \"warning\",\n\t\t\t\tcode: \"file_info_failed\",\n\t\t\t\tmessage: canonicalPath.error.message,\n\t\t\t\tpath: info.path,\n\t\t\t});\n\t\t}\n\t\treturn undefined;\n\t}\n\tconst target = await env.fileInfo(canonicalPath.value);\n\tif (!target.ok) {\n\t\tif (target.error.code !== \"not_found\") {\n\t\t\tdiagnostics.push({\n\t\t\t\ttype: \"warning\",\n\t\t\t\tcode: \"file_info_failed\",\n\t\t\t\tmessage: target.error.message,\n\t\t\t\tpath: info.path,\n\t\t\t});\n\t\t}\n\t\treturn undefined;\n\t}\n\treturn target.value.kind === \"file\" || target.value.kind === \"directory\" ? target.value.kind : undefined;\n}\n\nfunction joinEnvPath(base: string, child: string): string {\n\treturn `${base.replace(/\\/+$/, \"\")}/${child.replace(/^\\/+/, \"\")}`;\n}\n\nfunction dirnameEnvPath(path: string): string {\n\tconst normalized = path.replace(/\\/+$/, \"\");\n\tconst slashIndex = normalized.lastIndexOf(\"/\");\n\treturn slashIndex <= 0 ? \"/\" : normalized.slice(0, slashIndex);\n}\n\nfunction basenameEnvPath(path: string): string {\n\tconst normalized = path.replace(/\\/+$/, \"\");\n\tconst slashIndex = normalized.lastIndexOf(\"/\");\n\treturn slashIndex === -1 ? normalized : normalized.slice(slashIndex + 1);\n}\n\nfunction relativeEnvPath(root: string, path: string): string {\n\tconst normalizedRoot = root.replace(/\\/+$/, \"\");\n\tconst normalizedPath = path.replace(/\\/+$/, \"\");\n\tif (normalizedPath === normalizedRoot) return \"\";\n\treturn normalizedPath.startsWith(`${normalizedRoot}/`)\n\t\t? normalizedPath.slice(normalizedRoot.length + 1)\n\t\t: normalizedPath.replace(/^\\/+/, \"\");\n}\n"]}
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/harness/skills.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAA8C,KAAK,KAAK,EAAW,MAAM,YAAY,CAAC;AAOhH,MAAM,MAAM,mBAAmB,GAC5B,kBAAkB,GAClB,aAAa,GACb,aAAa,GACb,cAAc,GACd,kBAAkB,CAAC;AAEtB,6CAA6C;AAC7C,MAAM,WAAW,eAAe;IAC/B,gEAAgE;IAChE,IAAI,EAAE,SAAS,CAAC;IAChB,8BAA8B;IAC9B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;CACb;AAcD,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,WAAW,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,kEAAkE;AAClE,MAAM,MAAM,iBAAiB,CAAC,OAAO,IAAI;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,8DAA8D;AAC9D,MAAM,WAAW,YAAY,CAAC,MAAM,SAAS,KAAK,EAAE,OAAO;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;CAChB;AAED,kEAAkE;AAClE,MAAM,WAAW,sBAAsB,CAAC,OAAO,CAAE,SAAQ,eAAe;IACvE,MAAM,EAAE,OAAO,CAAC;CAChB;AAED,mEAAmE;AACnE,MAAM,WAAW,uBAAuB,CAAC,MAAM,SAAS,KAAK,EAAE,OAAO;IACrE,MAAM,EAAE,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACxC,WAAW,EAAE,sBAAsB,CAAC,OAAO,CAAC,EAAE,CAAC;CAC/C;AAYD,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,KAAK,EAAE,sBAAsB,CAAC,EAAE,MAAM,GAAG,MAAM,CAG3F;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuBtG;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,SAAS,KAAK,GAAG,KAAK,EAC5E,GAAG,EAAE,YAAY,EACjB,MAAM,EAAE,iBAAiB,CAAC,OAAO,CAAC,EAAE,EACpC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,KAAK,MAAM,GAClD,OAAO,CAAC,uBAAuB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAWnD"}
@@ -1 +1 @@
1
- {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/harness/skills.ts"],"names":[],"mappings":"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","sourcesContent":["import ignore from \"ignore\";\nimport { parse } from \"yaml\";\nimport { type ExecutionEnv, type FileError, type FileInfo, type Result, type Skill, toError } from \"./types.ts\";\n\nconst MAX_NAME_LENGTH = 64;\nconst MAX_DESCRIPTION_LENGTH = 1024;\nconst IGNORE_FILE_NAMES = [\".gitignore\", \".ignore\", \".fdignore\"];\ntype SkillPathKind = \"file\" | \"directory\";\n\nexport type SkillDiagnosticCode =\n\t| \"file_info_failed\"\n\t| \"list_failed\"\n\t| \"read_failed\"\n\t| \"parse_failed\"\n\t| \"invalid_metadata\";\n\n/** Warning produced while loading skills. */\nexport interface SkillDiagnostic {\n\t/** Diagnostic severity. Currently only warnings are emitted. */\n\ttype: \"warning\";\n\t/** Stable diagnostic code. */\n\tcode: SkillDiagnosticCode;\n\t/** Human-readable diagnostic message. */\n\tmessage: string;\n\t/** Path associated with the diagnostic. */\n\tpath: string;\n}\n\nfunction appendFileInfoDiagnostic(diagnostics: SkillDiagnostic[], error: FileError, path: string): void {\n\tif (error.code === \"not_found\") return;\n\tdiagnostics.push({ type: \"warning\", code: \"file_info_failed\", message: error.message, path });\n}\n\ninterface SkillFrontmatter {\n\tname?: string;\n\tdescription?: string;\n\t\"disable-model-invocation\"?: boolean;\n\t[key: string]: unknown;\n}\n\n/** Skills and warnings produced by a directory load. */\nexport interface LoadSkillsResult {\n\tskills: Skill[];\n\tdiagnostics: SkillDiagnostic[];\n}\n\n/** Source-tagged directory passed to the sourced skill loader. */\nexport type SourcedSkillInput<TSource> = {\n\tpath: string;\n\tsource: TSource;\n};\n\n/** Loaded skill paired with its caller-defined provenance. */\nexport interface SourcedSkill<TSkill extends Skill, TSource> {\n\tskill: TSkill;\n\tsource: TSource;\n}\n\n/** Skill diagnostic paired with its caller-defined provenance. */\nexport interface SourcedSkillDiagnostic<TSource> extends SkillDiagnostic {\n\tsource: TSource;\n}\n\n/** Skills and diagnostics produced by a sourced directory load. */\nexport interface LoadSourcedSkillsResult<TSkill extends Skill, TSource> {\n\tskills: SourcedSkill<TSkill, TSource>[];\n\tdiagnostics: SourcedSkillDiagnostic<TSource>[];\n}\n\ninterface SkillFileLoadResult {\n\tskill: Skill | null;\n\tdiagnostics: SkillDiagnostic[];\n}\n\ntype ParsedFrontmatter<T> = {\n\tfrontmatter: T;\n\tbody: string;\n};\n\n/** Format a skill invocation prompt, optionally appending additional user instructions. */\nexport function formatSkillInvocation(skill: Skill, additionalInstructions?: string): string {\n\tconst skillBlock = `<skill name=\"${skill.name}\" location=\"${skill.filePath}\">\\nReferences are relative to ${dirnameEnvPath(skill.filePath)}.\\n\\n${skill.content}\\n</skill>`;\n\treturn additionalInstructions ? `${skillBlock}\\n\\n${additionalInstructions}` : skillBlock;\n}\n\n/**\n * Load skills from one or more directories.\n *\n * Traverses directories recursively, loads `SKILL.md` files, loads direct root `.md` files as skills, honors ignore files,\n * and returns diagnostics for invalid skill files. Missing input directories are skipped.\n */\nexport async function loadSkills(env: ExecutionEnv, dirs: string | string[]): Promise<LoadSkillsResult> {\n\tconst skills: Skill[] = [];\n\tconst diagnostics: SkillDiagnostic[] = [];\n\tfor (const dir of Array.isArray(dirs) ? dirs : [dirs]) {\n\t\tconst rootInfoResult = await env.fileInfo(dir);\n\t\tif (!rootInfoResult.ok) {\n\t\t\tif (rootInfoResult.error.code !== \"not_found\") {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\ttype: \"warning\",\n\t\t\t\t\tcode: \"file_info_failed\",\n\t\t\t\t\tmessage: rootInfoResult.error.message,\n\t\t\t\t\tpath: dir,\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tconst rootInfo = rootInfoResult.value;\n\t\tif ((await resolveKind(env, rootInfo, diagnostics)) !== \"directory\") continue;\n\t\tconst result = await loadSkillsFromDirInternal(env, rootInfo.path, true, ignore(), rootInfo.path);\n\t\tskills.push(...result.skills);\n\t\tdiagnostics.push(...result.diagnostics);\n\t}\n\treturn { skills, diagnostics };\n}\n\n/**\n * Load skills from source-tagged directories.\n *\n * Source values are preserved exactly and attached to every loaded skill and diagnostic. The agent package does not\n * interpret source values; applications define their own provenance shape.\n */\nexport async function loadSourcedSkills<TSource, TSkill extends Skill = Skill>(\n\tenv: ExecutionEnv,\n\tinputs: SourcedSkillInput<TSource>[],\n\tmapSkill?: (skill: Skill, source: TSource) => TSkill,\n): Promise<LoadSourcedSkillsResult<TSkill, TSource>> {\n\tconst skills: SourcedSkill<TSkill, TSource>[] = [];\n\tconst diagnostics: SourcedSkillDiagnostic<TSource>[] = [];\n\tfor (const input of inputs) {\n\t\tconst result = await loadSkills(env, input.path);\n\t\tfor (const skill of result.skills) {\n\t\t\tskills.push({ skill: mapSkill ? mapSkill(skill, input.source) : (skill as TSkill), source: input.source });\n\t\t}\n\t\tfor (const diagnostic of result.diagnostics) diagnostics.push({ ...diagnostic, source: input.source });\n\t}\n\treturn { skills, diagnostics };\n}\n\nasync function findDirectorySkill(\n\tenv: ExecutionEnv,\n\tentries: FileInfo[],\n\tignoreMatcher: ignore.Ignore,\n\trootDir: string,\n\tdiagnostics: SkillDiagnostic[],\n): Promise<SkillFileLoadResult | undefined> {\n\tfor (const entry of entries) {\n\t\tif (entry.name !== \"SKILL.md\") continue;\n\t\tif ((await resolveKind(env, entry, diagnostics)) !== \"file\") continue;\n\t\tif (ignoreMatcher.ignores(relativeEnvPath(rootDir, entry.path))) continue;\n\t\treturn loadSkillFromFile(env, entry.path);\n\t}\n\treturn undefined;\n}\n\nfunction shouldSkipChildSkillEntry(entry: FileInfo): boolean {\n\treturn entry.name.startsWith(\".\") || entry.name === \"node_modules\";\n}\n\nasync function loadChildSkillEntry(\n\tenv: ExecutionEnv,\n\tentry: FileInfo,\n\tincludeRootFiles: boolean,\n\tignoreMatcher: ignore.Ignore,\n\trootDir: string,\n\tdiagnostics: SkillDiagnostic[],\n): Promise<LoadSkillsResult> {\n\tif (shouldSkipChildSkillEntry(entry)) return { skills: [], diagnostics: [] };\n\tconst kind = await resolveKind(env, entry, diagnostics);\n\tif (!kind) return { skills: [], diagnostics: [] };\n\tconst relPath = relativeEnvPath(rootDir, entry.path);\n\tconst ignorePath = kind === \"directory\" ? `${relPath}/` : relPath;\n\tif (ignoreMatcher.ignores(ignorePath)) return { skills: [], diagnostics: [] };\n\tif (kind === \"directory\") return loadSkillsFromDirInternal(env, entry.path, false, ignoreMatcher, rootDir);\n\tif (!includeRootFiles || !entry.name.endsWith(\".md\")) return { skills: [], diagnostics: [] };\n\tconst result = await loadSkillFromFile(env, entry.path);\n\treturn { skills: result.skill ? [result.skill] : [], diagnostics: result.diagnostics };\n}\n\nfunction mergeSkillsResult(target: LoadSkillsResult, source: LoadSkillsResult): void {\n\ttarget.skills.push(...source.skills);\n\ttarget.diagnostics.push(...source.diagnostics);\n}\n\nasync function loadSkillsFromDirInternal(\n\tenv: ExecutionEnv,\n\tdir: string,\n\tincludeRootFiles: boolean,\n\tignoreMatcher: ignore.Ignore,\n\trootDir: string,\n): Promise<LoadSkillsResult> {\n\tconst result: LoadSkillsResult = { skills: [], diagnostics: [] };\n\tconst dirInfoResult = await env.fileInfo(dir);\n\tif (!dirInfoResult.ok) {\n\t\tappendFileInfoDiagnostic(result.diagnostics, dirInfoResult.error, dir);\n\t\treturn result;\n\t}\n\tif ((await resolveKind(env, dirInfoResult.value, result.diagnostics)) !== \"directory\") return result;\n\n\tawait addIgnoreRules(env, ignoreMatcher, dir, rootDir, result.diagnostics);\n\tconst entriesResult = await env.listDir(dir);\n\tif (!entriesResult.ok) {\n\t\tresult.diagnostics.push({\n\t\t\ttype: \"warning\",\n\t\t\tcode: \"list_failed\",\n\t\t\tmessage: entriesResult.error.message,\n\t\t\tpath: dir,\n\t\t});\n\t\treturn result;\n\t}\n\tconst entries = entriesResult.value;\n\tconst directorySkill = await findDirectorySkill(env, entries, ignoreMatcher, rootDir, result.diagnostics);\n\tif (directorySkill) {\n\t\tif (directorySkill.skill) result.skills.push(directorySkill.skill);\n\t\tresult.diagnostics.push(...directorySkill.diagnostics);\n\t\treturn result;\n\t}\n\n\tfor (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {\n\t\tmergeSkillsResult(\n\t\t\tresult,\n\t\t\tawait loadChildSkillEntry(env, entry, includeRootFiles, ignoreMatcher, rootDir, result.diagnostics),\n\t\t);\n\t}\n\treturn result;\n}\n\nasync function addIgnoreRules(\n\tenv: ExecutionEnv,\n\tig: ignore.Ignore,\n\tdir: string,\n\trootDir: string,\n\tdiagnostics: SkillDiagnostic[],\n): Promise<void> {\n\tconst relativeDir = relativeEnvPath(rootDir, dir);\n\tconst prefix = relativeDir ? `${relativeDir}/` : \"\";\n\n\tfor (const filename of IGNORE_FILE_NAMES) {\n\t\tconst ignorePath = joinEnvPath(dir, filename);\n\t\tconst info = await env.fileInfo(ignorePath);\n\t\tif (!info.ok) {\n\t\t\tif (info.error.code !== \"not_found\") {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\ttype: \"warning\",\n\t\t\t\t\tcode: \"file_info_failed\",\n\t\t\t\t\tmessage: info.error.message,\n\t\t\t\t\tpath: ignorePath,\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (info.value.kind !== \"file\") continue;\n\t\tconst content = await env.readTextFile(ignorePath);\n\t\tif (!content.ok) {\n\t\t\tdiagnostics.push({ type: \"warning\", code: \"read_failed\", message: content.error.message, path: ignorePath });\n\t\t\tcontinue;\n\t\t}\n\t\tconst patterns = content.value\n\t\t\t.split(/\\r?\\n/)\n\t\t\t.map((line) => prefixIgnorePattern(line, prefix))\n\t\t\t.filter((line): line is string => Boolean(line));\n\t\tif (patterns.length > 0) ig.add(patterns);\n\t}\n}\n\nfunction prefixIgnorePattern(line: string, prefix: string): string | null {\n\tconst trimmed = line.trim();\n\tif (!trimmed) return null;\n\tif (trimmed.startsWith(\"#\") && !trimmed.startsWith(\"\\\\#\")) return null;\n\n\tlet pattern = line;\n\tlet negated = false;\n\tif (pattern.startsWith(\"!\")) {\n\t\tnegated = true;\n\t\tpattern = pattern.slice(1);\n\t} else if (pattern.startsWith(\"\\\\!\")) {\n\t\tpattern = pattern.slice(1);\n\t}\n\tif (pattern.startsWith(\"/\")) pattern = pattern.slice(1);\n\tconst prefixed = prefix ? `${prefix}${pattern}` : pattern;\n\treturn negated ? `!${prefixed}` : prefixed;\n}\n\nasync function loadSkillFromFile(env: ExecutionEnv, filePath: string): Promise<SkillFileLoadResult> {\n\tconst diagnostics: SkillDiagnostic[] = [];\n\tconst rawContent = await env.readTextFile(filePath);\n\tif (!rawContent.ok) {\n\t\tdiagnostics.push({ type: \"warning\", code: \"read_failed\", message: rawContent.error.message, path: filePath });\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\tconst parsed = parseFrontmatter<SkillFrontmatter>(rawContent.value);\n\tif (!parsed.ok) {\n\t\tdiagnostics.push({ type: \"warning\", code: \"parse_failed\", message: parsed.error.message, path: filePath });\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\tconst { frontmatter, body } = parsed.value;\n\tconst skillDir = dirnameEnvPath(filePath);\n\tconst parentDirName = basenameEnvPath(skillDir);\n\tconst description = typeof frontmatter.description === \"string\" ? frontmatter.description : undefined;\n\n\tfor (const error of validateDescription(description)) {\n\t\tdiagnostics.push({ type: \"warning\", code: \"invalid_metadata\", message: error, path: filePath });\n\t}\n\n\tconst frontmatterName = typeof frontmatter.name === \"string\" ? frontmatter.name : undefined;\n\tconst name = frontmatterName || parentDirName;\n\tfor (const error of validateName(name, parentDirName)) {\n\t\tdiagnostics.push({ type: \"warning\", code: \"invalid_metadata\", message: error, path: filePath });\n\t}\n\n\tif (!description || description.trim() === \"\") {\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\treturn {\n\t\tskill: {\n\t\t\tname,\n\t\t\tdescription,\n\t\t\tcontent: body,\n\t\t\tfilePath,\n\t\t\tdisableModelInvocation: frontmatter[\"disable-model-invocation\"] === true,\n\t\t},\n\t\tdiagnostics,\n\t};\n}\n\nfunction validateName(name: string, parentDirName: string): string[] {\n\tconst errors: string[] = [];\n\tif (name !== parentDirName) errors.push(`name \"${name}\" does not match parent directory \"${parentDirName}\"`);\n\tif (name.length > MAX_NAME_LENGTH) errors.push(`name exceeds ${MAX_NAME_LENGTH} characters (${name.length})`);\n\tif (!/^[a-z0-9-]+$/.test(name)) {\n\t\terrors.push(\"name contains invalid characters (must be lowercase a-z, 0-9, hyphens only)\");\n\t}\n\tif (name.startsWith(\"-\") || name.endsWith(\"-\")) errors.push(\"name must not start or end with a hyphen\");\n\tif (name.includes(\"--\")) errors.push(\"name must not contain consecutive hyphens\");\n\treturn errors;\n}\n\nfunction validateDescription(description: string | undefined): string[] {\n\tconst errors: string[] = [];\n\tif (!description || description.trim() === \"\") {\n\t\terrors.push(\"description is required\");\n\t} else if (description.length > MAX_DESCRIPTION_LENGTH) {\n\t\terrors.push(`description exceeds ${MAX_DESCRIPTION_LENGTH} characters (${description.length})`);\n\t}\n\treturn errors;\n}\n\nfunction parseFrontmatter<T extends Record<string, unknown>>(content: string): Result<ParsedFrontmatter<T>, Error> {\n\ttry {\n\t\tconst normalized = content.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\t\tif (!normalized.startsWith(\"---\")) return { ok: true, value: { frontmatter: {} as T, body: normalized } };\n\t\tconst endIndex = normalized.indexOf(\"\\n---\", 3);\n\t\tif (endIndex === -1) return { ok: true, value: { frontmatter: {} as T, body: normalized } };\n\t\tconst yamlString = normalized.slice(4, endIndex);\n\t\tconst body = normalized.slice(endIndex + 4).trim();\n\t\treturn { ok: true, value: { frontmatter: (parse(yamlString) ?? {}) as T, body } };\n\t} catch (error) {\n\t\treturn { ok: false, error: toError(error) };\n\t}\n}\n\nasync function resolveKind(\n\tenv: ExecutionEnv,\n\tinfo: FileInfo,\n\tdiagnostics: SkillDiagnostic[],\n): Promise<SkillPathKind | undefined> {\n\tif (info.kind === \"file\" || info.kind === \"directory\") return info.kind;\n\tconst canonicalPath = await env.canonicalPath(info.path);\n\tif (!canonicalPath.ok) {\n\t\tif (canonicalPath.error.code !== \"not_found\") {\n\t\t\tdiagnostics.push({\n\t\t\t\ttype: \"warning\",\n\t\t\t\tcode: \"file_info_failed\",\n\t\t\t\tmessage: canonicalPath.error.message,\n\t\t\t\tpath: info.path,\n\t\t\t});\n\t\t}\n\t\treturn undefined;\n\t}\n\tconst target = await env.fileInfo(canonicalPath.value);\n\tif (!target.ok) {\n\t\tif (target.error.code !== \"not_found\") {\n\t\t\tdiagnostics.push({\n\t\t\t\ttype: \"warning\",\n\t\t\t\tcode: \"file_info_failed\",\n\t\t\t\tmessage: target.error.message,\n\t\t\t\tpath: info.path,\n\t\t\t});\n\t\t}\n\t\treturn undefined;\n\t}\n\treturn target.value.kind === \"file\" || target.value.kind === \"directory\" ? target.value.kind : undefined;\n}\n\nfunction joinEnvPath(base: string, child: string): string {\n\treturn `${base.replace(/\\/+$/, \"\")}/${child.replace(/^\\/+/, \"\")}`;\n}\n\nfunction dirnameEnvPath(path: string): string {\n\tconst normalized = path.replace(/\\/+$/, \"\");\n\tconst slashIndex = normalized.lastIndexOf(\"/\");\n\treturn slashIndex <= 0 ? \"/\" : normalized.slice(0, slashIndex);\n}\n\nfunction basenameEnvPath(path: string): string {\n\tconst normalized = path.replace(/\\/+$/, \"\");\n\tconst slashIndex = normalized.lastIndexOf(\"/\");\n\treturn slashIndex === -1 ? normalized : normalized.slice(slashIndex + 1);\n}\n\nfunction relativeEnvPath(root: string, path: string): string {\n\tconst normalizedRoot = root.replace(/\\/+$/, \"\");\n\tconst normalizedPath = path.replace(/\\/+$/, \"\");\n\tif (normalizedPath === normalizedRoot) return \"\";\n\treturn normalizedPath.startsWith(`${normalizedRoot}/`)\n\t\t? normalizedPath.slice(normalizedRoot.length + 1)\n\t\t: normalizedPath.replace(/^\\/+/, \"\");\n}\n"]}
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/harness/skills.ts"],"names":[],"mappings":"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","sourcesContent":["import ignore from \"ignore\";\nimport { parse } from \"yaml\";\nimport { type ExecutionEnv, type FileError, type FileInfo, type Result, type Skill, toError } from \"./types.ts\";\n\nconst MAX_NAME_LENGTH = 64;\nconst MAX_DESCRIPTION_LENGTH = 1024;\nconst IGNORE_FILE_NAMES = [\".gitignore\", \".ignore\", \".fdignore\"];\ntype SkillPathKind = \"file\" | \"directory\";\n\nexport type SkillDiagnosticCode =\n\t| \"file_info_failed\"\n\t| \"list_failed\"\n\t| \"read_failed\"\n\t| \"parse_failed\"\n\t| \"invalid_metadata\";\n\n/** Warning produced while loading skills. */\nexport interface SkillDiagnostic {\n\t/** Diagnostic severity. Currently only warnings are emitted. */\n\ttype: \"warning\";\n\t/** Stable diagnostic code. */\n\tcode: SkillDiagnosticCode;\n\t/** Human-readable diagnostic message. */\n\tmessage: string;\n\t/** Path associated with the diagnostic. */\n\tpath: string;\n}\n\nfunction appendFileInfoDiagnostic(diagnostics: SkillDiagnostic[], error: FileError, path: string): void {\n\tif (error.code === \"not_found\") return;\n\tdiagnostics.push({ type: \"warning\", code: \"file_info_failed\", message: error.message, path });\n}\n\ninterface SkillFrontmatter {\n\tname?: string;\n\tdescription?: string;\n\t\"disable-model-invocation\"?: boolean;\n\t[key: string]: unknown;\n}\n\n/** Skills and warnings produced by a directory load. */\nexport interface LoadSkillsResult {\n\tskills: Skill[];\n\tdiagnostics: SkillDiagnostic[];\n}\n\n/** Source-tagged directory passed to the sourced skill loader. */\nexport type SourcedSkillInput<TSource> = {\n\tpath: string;\n\tsource: TSource;\n};\n\n/** Loaded skill paired with its caller-defined provenance. */\nexport interface SourcedSkill<TSkill extends Skill, TSource> {\n\tskill: TSkill;\n\tsource: TSource;\n}\n\n/** Skill diagnostic paired with its caller-defined provenance. */\nexport interface SourcedSkillDiagnostic<TSource> extends SkillDiagnostic {\n\tsource: TSource;\n}\n\n/** Skills and diagnostics produced by a sourced directory load. */\nexport interface LoadSourcedSkillsResult<TSkill extends Skill, TSource> {\n\tskills: SourcedSkill<TSkill, TSource>[];\n\tdiagnostics: SourcedSkillDiagnostic<TSource>[];\n}\n\ninterface SkillFileLoadResult {\n\tskill: Skill | null;\n\tdiagnostics: SkillDiagnostic[];\n}\n\ntype ParsedFrontmatter<T> = {\n\tfrontmatter: T;\n\tbody: string;\n};\n\n/** Format a skill invocation prompt, optionally appending additional user instructions. */\nexport function formatSkillInvocation(skill: Skill, additionalInstructions?: string): string {\n\tconst skillBlock = `<skill name=\"${skill.name}\" location=\"${skill.filePath}\">\\nReferences are relative to ${dirnameEnvPath(skill.filePath)}.\\n\\n${skill.content}\\n</skill>`;\n\treturn additionalInstructions ? `${skillBlock}\\n\\n${additionalInstructions}` : skillBlock;\n}\n\n/**\n * Load skills from one or more directories.\n *\n * Traverses directories recursively, loads `SKILL.md` files, loads direct root `.md` files as skills, honors ignore files,\n * and returns diagnostics for invalid skill files. Missing input directories are skipped.\n */\nexport async function loadSkills(env: ExecutionEnv, dirs: string | string[]): Promise<LoadSkillsResult> {\n\tconst skills: Skill[] = [];\n\tconst diagnostics: SkillDiagnostic[] = [];\n\tfor (const dir of Array.isArray(dirs) ? dirs : [dirs]) {\n\t\tconst rootInfoResult = await env.fileInfo(dir);\n\t\tif (!rootInfoResult.ok) {\n\t\t\tif (rootInfoResult.error.code !== \"not_found\") {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\ttype: \"warning\",\n\t\t\t\t\tcode: \"file_info_failed\",\n\t\t\t\t\tmessage: rootInfoResult.error.message,\n\t\t\t\t\tpath: dir,\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tconst rootInfo = rootInfoResult.value;\n\t\tif ((await resolveKind(env, rootInfo, diagnostics)) !== \"directory\") continue;\n\t\tconst result = await loadSkillsFromDirInternal(env, rootInfo.path, true, ignore(), rootInfo.path);\n\t\tskills.push(...result.skills);\n\t\tdiagnostics.push(...result.diagnostics);\n\t}\n\treturn { skills, diagnostics };\n}\n\n/**\n * Load skills from source-tagged directories.\n *\n * Source values are preserved exactly and attached to every loaded skill and diagnostic. The agent package does not\n * interpret source values; applications define their own provenance shape.\n */\nexport async function loadSourcedSkills<TSource, TSkill extends Skill = Skill>(\n\tenv: ExecutionEnv,\n\tinputs: SourcedSkillInput<TSource>[],\n\tmapSkill?: (skill: Skill, source: TSource) => TSkill,\n): Promise<LoadSourcedSkillsResult<TSkill, TSource>> {\n\tconst skills: SourcedSkill<TSkill, TSource>[] = [];\n\tconst diagnostics: SourcedSkillDiagnostic<TSource>[] = [];\n\tfor (const input of inputs) {\n\t\tconst result = await loadSkills(env, input.path);\n\t\tfor (const skill of result.skills) {\n\t\t\tskills.push({ skill: mapSkill ? mapSkill(skill, input.source) : (skill as TSkill), source: input.source });\n\t\t}\n\t\tfor (const diagnostic of result.diagnostics) diagnostics.push({ ...diagnostic, source: input.source });\n\t}\n\treturn { skills, diagnostics };\n}\n\nasync function findDirectorySkill(\n\tenv: ExecutionEnv,\n\tentries: FileInfo[],\n\tignoreMatcher: ignore.Ignore,\n\trootDir: string,\n\tdiagnostics: SkillDiagnostic[],\n): Promise<SkillFileLoadResult | undefined> {\n\tfor (const entry of entries) {\n\t\tif (entry.name !== \"SKILL.md\") continue;\n\t\tif ((await resolveKind(env, entry, diagnostics)) !== \"file\") continue;\n\t\tif (ignoreMatcher.ignores(relativeEnvPath(rootDir, entry.path))) continue;\n\t\treturn loadSkillFromFile(env, entry.path);\n\t}\n\treturn undefined;\n}\n\nfunction shouldSkipChildSkillEntry(entry: FileInfo): boolean {\n\treturn entry.name.startsWith(\".\") || entry.name === \"node_modules\";\n}\n\nasync function loadChildSkillEntry(\n\tenv: ExecutionEnv,\n\tentry: FileInfo,\n\tincludeRootFiles: boolean,\n\tignoreMatcher: ignore.Ignore,\n\trootDir: string,\n\tdiagnostics: SkillDiagnostic[],\n): Promise<LoadSkillsResult> {\n\tif (shouldSkipChildSkillEntry(entry)) return { skills: [], diagnostics: [] };\n\tconst kind = await resolveKind(env, entry, diagnostics);\n\tif (!kind) return { skills: [], diagnostics: [] };\n\tconst relPath = relativeEnvPath(rootDir, entry.path);\n\tconst ignorePath = kind === \"directory\" ? `${relPath}/` : relPath;\n\tif (ignoreMatcher.ignores(ignorePath)) return { skills: [], diagnostics: [] };\n\tif (kind === \"directory\") return loadSkillsFromDirInternal(env, entry.path, false, ignoreMatcher, rootDir);\n\tif (!includeRootFiles || !entry.name.endsWith(\".md\")) return { skills: [], diagnostics: [] };\n\tconst result = await loadSkillFromFile(env, entry.path);\n\treturn { skills: result.skill ? [result.skill] : [], diagnostics: result.diagnostics };\n}\n\nfunction mergeSkillsResult(target: LoadSkillsResult, source: LoadSkillsResult): void {\n\ttarget.skills.push(...source.skills);\n\ttarget.diagnostics.push(...source.diagnostics);\n}\n\nasync function loadSkillsFromDirInternal(\n\tenv: ExecutionEnv,\n\tdir: string,\n\tincludeRootFiles: boolean,\n\tignoreMatcher: ignore.Ignore,\n\trootDir: string,\n): Promise<LoadSkillsResult> {\n\tconst result: LoadSkillsResult = { skills: [], diagnostics: [] };\n\tconst dirInfoResult = await env.fileInfo(dir);\n\tif (!dirInfoResult.ok) {\n\t\tappendFileInfoDiagnostic(result.diagnostics, dirInfoResult.error, dir);\n\t\treturn result;\n\t}\n\tif ((await resolveKind(env, dirInfoResult.value, result.diagnostics)) !== \"directory\") return result;\n\n\tawait addIgnoreRules(env, ignoreMatcher, dir, rootDir, result.diagnostics);\n\tconst entriesResult = await env.listDir(dir);\n\tif (!entriesResult.ok) {\n\t\tresult.diagnostics.push({\n\t\t\ttype: \"warning\",\n\t\t\tcode: \"list_failed\",\n\t\t\tmessage: entriesResult.error.message,\n\t\t\tpath: dir,\n\t\t});\n\t\treturn result;\n\t}\n\tconst entries = entriesResult.value;\n\tconst directorySkill = await findDirectorySkill(env, entries, ignoreMatcher, rootDir, result.diagnostics);\n\tif (directorySkill) {\n\t\tif (directorySkill.skill) result.skills.push(directorySkill.skill);\n\t\tresult.diagnostics.push(...directorySkill.diagnostics);\n\t\treturn result;\n\t}\n\n\tfor (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {\n\t\tmergeSkillsResult(\n\t\t\tresult,\n\t\t\tawait loadChildSkillEntry(env, entry, includeRootFiles, ignoreMatcher, rootDir, result.diagnostics),\n\t\t);\n\t}\n\treturn result;\n}\n\nasync function addIgnoreRules(\n\tenv: ExecutionEnv,\n\tig: ignore.Ignore,\n\tdir: string,\n\trootDir: string,\n\tdiagnostics: SkillDiagnostic[],\n): Promise<void> {\n\tconst relativeDir = relativeEnvPath(rootDir, dir);\n\tconst prefix = relativeDir ? `${relativeDir}/` : \"\";\n\n\tfor (const filename of IGNORE_FILE_NAMES) {\n\t\tconst ignorePath = joinEnvPath(dir, filename);\n\t\tconst info = await env.fileInfo(ignorePath);\n\t\tif (!info.ok) {\n\t\t\tif (info.error.code !== \"not_found\") {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\ttype: \"warning\",\n\t\t\t\t\tcode: \"file_info_failed\",\n\t\t\t\t\tmessage: info.error.message,\n\t\t\t\t\tpath: ignorePath,\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (info.value.kind !== \"file\") continue;\n\t\tconst content = await env.readTextFile(ignorePath);\n\t\tif (!content.ok) {\n\t\t\tdiagnostics.push({ type: \"warning\", code: \"read_failed\", message: content.error.message, path: ignorePath });\n\t\t\tcontinue;\n\t\t}\n\t\tconst patterns = content.value\n\t\t\t.split(/\\r?\\n/)\n\t\t\t.map((line) => prefixIgnorePattern(line, prefix))\n\t\t\t.filter((line): line is string => Boolean(line));\n\t\tif (patterns.length > 0) ig.add(patterns);\n\t}\n}\n\nfunction prefixIgnorePattern(line: string, prefix: string): string | null {\n\tconst trimmed = line.trim();\n\tif (!trimmed) return null;\n\tif (trimmed.startsWith(\"#\") && !trimmed.startsWith(\"\\\\#\")) return null;\n\n\tlet pattern = line;\n\tlet negated = false;\n\tif (pattern.startsWith(\"!\")) {\n\t\tnegated = true;\n\t\tpattern = pattern.slice(1);\n\t} else if (pattern.startsWith(\"\\\\!\")) {\n\t\tpattern = pattern.slice(1);\n\t}\n\tif (pattern.startsWith(\"/\")) pattern = pattern.slice(1);\n\tconst prefixed = prefix ? `${prefix}${pattern}` : pattern;\n\treturn negated ? `!${prefixed}` : prefixed;\n}\n\nasync function loadSkillFromFile(env: ExecutionEnv, filePath: string): Promise<SkillFileLoadResult> {\n\tconst diagnostics: SkillDiagnostic[] = [];\n\tconst rawContent = await env.readTextFile(filePath);\n\tif (!rawContent.ok) {\n\t\tdiagnostics.push({ type: \"warning\", code: \"read_failed\", message: rawContent.error.message, path: filePath });\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\tconst parsed = parseFrontmatter<SkillFrontmatter>(rawContent.value);\n\tif (!parsed.ok) {\n\t\tdiagnostics.push({ type: \"warning\", code: \"parse_failed\", message: parsed.error.message, path: filePath });\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\tconst { frontmatter, body } = parsed.value;\n\tconst skillDir = dirnameEnvPath(filePath);\n\tconst parentDirName = basenameEnvPath(skillDir);\n\tconst description = typeof frontmatter.description === \"string\" ? frontmatter.description : undefined;\n\n\tfor (const error of validateDescription(description)) {\n\t\tdiagnostics.push({ type: \"warning\", code: \"invalid_metadata\", message: error, path: filePath });\n\t}\n\n\tconst frontmatterName = typeof frontmatter.name === \"string\" ? frontmatter.name : undefined;\n\tconst name = frontmatterName || parentDirName;\n\tfor (const error of validateName(name, parentDirName)) {\n\t\tdiagnostics.push({ type: \"warning\", code: \"invalid_metadata\", message: error, path: filePath });\n\t}\n\n\tif (!description || description.trim() === \"\") {\n\t\treturn { skill: null, diagnostics };\n\t}\n\n\treturn {\n\t\tskill: {\n\t\t\tname,\n\t\t\tdescription,\n\t\t\tcontent: body,\n\t\t\tfilePath,\n\t\t\tdisableModelInvocation: frontmatter[\"disable-model-invocation\"] === true,\n\t\t},\n\t\tdiagnostics,\n\t};\n}\n\nfunction validateName(name: string, parentDirName: string): string[] {\n\tconst errors: string[] = [];\n\tif (name !== parentDirName) errors.push(`name \"${name}\" does not match parent directory \"${parentDirName}\"`);\n\tif (name.length > MAX_NAME_LENGTH) errors.push(`name exceeds ${MAX_NAME_LENGTH} characters (${name.length})`);\n\tif (!/^[a-z0-9-]+$/.test(name)) {\n\t\terrors.push(\"name contains invalid characters (must be lowercase a-z, 0-9, hyphens only)\");\n\t}\n\tif (name.startsWith(\"-\") || name.endsWith(\"-\")) errors.push(\"name must not start or end with a hyphen\");\n\tif (name.includes(\"--\")) errors.push(\"name must not contain consecutive hyphens\");\n\treturn errors;\n}\n\nfunction validateDescription(description: string | undefined): string[] {\n\tconst errors: string[] = [];\n\tif (!description || description.trim() === \"\") {\n\t\terrors.push(\"description is required\");\n\t} else if (description.length > MAX_DESCRIPTION_LENGTH) {\n\t\terrors.push(`description exceeds ${MAX_DESCRIPTION_LENGTH} characters (${description.length})`);\n\t}\n\treturn errors;\n}\n\nfunction parseFrontmatter<T extends Record<string, unknown>>(content: string): Result<ParsedFrontmatter<T>, Error> {\n\ttry {\n\t\tconst normalized = content.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\t\tif (!normalized.startsWith(\"---\")) return { ok: true, value: { frontmatter: {} as T, body: normalized } };\n\t\tconst endIndex = normalized.indexOf(\"\\n---\", 3);\n\t\tif (endIndex === -1) return { ok: true, value: { frontmatter: {} as T, body: normalized } };\n\t\tconst yamlString = normalized.slice(4, endIndex);\n\t\tconst body = normalized.slice(endIndex + 4).trim();\n\t\treturn { ok: true, value: { frontmatter: (parse(yamlString) ?? {}) as T, body } };\n\t} catch (error) {\n\t\treturn { ok: false, error: toError(error) };\n\t}\n}\n\nasync function resolveKind(\n\tenv: ExecutionEnv,\n\tinfo: FileInfo,\n\tdiagnostics: SkillDiagnostic[],\n): Promise<SkillPathKind | undefined> {\n\tif (info.kind === \"file\" || info.kind === \"directory\") return info.kind;\n\tconst canonicalPath = await env.canonicalPath(info.path);\n\tif (!canonicalPath.ok) {\n\t\tif (canonicalPath.error.code !== \"not_found\") {\n\t\t\tdiagnostics.push({\n\t\t\t\ttype: \"warning\",\n\t\t\t\tcode: \"file_info_failed\",\n\t\t\t\tmessage: canonicalPath.error.message,\n\t\t\t\tpath: info.path,\n\t\t\t});\n\t\t}\n\t\treturn undefined;\n\t}\n\tconst target = await env.fileInfo(canonicalPath.value);\n\tif (!target.ok) {\n\t\tif (target.error.code !== \"not_found\") {\n\t\t\tdiagnostics.push({\n\t\t\t\ttype: \"warning\",\n\t\t\t\tcode: \"file_info_failed\",\n\t\t\t\tmessage: target.error.message,\n\t\t\t\tpath: info.path,\n\t\t\t});\n\t\t}\n\t\treturn undefined;\n\t}\n\treturn target.value.kind === \"file\" || target.value.kind === \"directory\" ? target.value.kind : undefined;\n}\n\nfunction joinEnvPath(base: string, child: string): string {\n\treturn `${base.replace(/\\/+$/, \"\")}/${child.replace(/^\\/+/, \"\")}`;\n}\n\nfunction dirnameEnvPath(path: string): string {\n\tconst normalized = path.replace(/\\/+$/, \"\");\n\tconst slashIndex = normalized.lastIndexOf(\"/\");\n\treturn slashIndex <= 0 ? \"/\" : normalized.slice(0, slashIndex);\n}\n\nfunction basenameEnvPath(path: string): string {\n\tconst normalized = path.replace(/\\/+$/, \"\");\n\tconst slashIndex = normalized.lastIndexOf(\"/\");\n\treturn slashIndex === -1 ? normalized : normalized.slice(slashIndex + 1);\n}\n\nfunction relativeEnvPath(root: string, path: string): string {\n\tconst normalizedRoot = root.replace(/\\/+$/, \"\");\n\tconst normalizedPath = path.replace(/\\/+$/, \"\");\n\tif (normalizedPath === normalizedRoot) return \"\";\n\treturn normalizedPath.startsWith(`${normalizedRoot}/`)\n\t\t? normalizedPath.slice(normalizedRoot.length + 1)\n\t\t: normalizedPath.replace(/^\\/+/, \"\");\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/harness/system-prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAsBnE","sourcesContent":["import type { Skill } from \"./types.ts\";\n\nexport function formatSkillsForSystemPrompt(skills: Skill[]): string {\n\tconst visibleSkills = skills.filter((skill) => !skill.disableModelInvocation);\n\tif (visibleSkills.length === 0) return \"\";\n\n\tconst lines = [\n\t\t\"The following skills provide specialized instructions for specific tasks.\",\n\t\t\"Read the full skill file when the task matches its description.\",\n\t\t\"When a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\",\n\t\t\"\",\n\t\t\"<available_skills>\",\n\t];\n\n\tfor (const skill of visibleSkills) {\n\t\tlines.push(\" <skill>\");\n\t\tlines.push(` <name>${escapeXml(skill.name)}</name>`);\n\t\tlines.push(` <description>${escapeXml(skill.description)}</description>`);\n\t\tlines.push(` <location>${escapeXml(skill.filePath)}</location>`);\n\t\tlines.push(\" </skill>\");\n\t}\n\n\tlines.push(\"</available_skills>\");\n\treturn lines.join(\"\\n\");\n}\n\nfunction escapeXml(value: string): string {\n\treturn value\n\t\t.replace(/&/g, \"&amp;\")\n\t\t.replace(/</g, \"&lt;\")\n\t\t.replace(/>/g, \"&gt;\")\n\t\t.replace(/\"/g, \"&quot;\")\n\t\t.replace(/'/g, \"&apos;\");\n}\n"]}
1
+ {"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/harness/system-prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAsBnE"}
@@ -1 +1 @@
1
- {"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/harness/system-prompt.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,2BAA2B,CAAC,MAAe,EAAU;IACpE,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC9E,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE1C,MAAM,KAAK,GAAG;QACb,2EAA2E;QAC3E,iEAAiE;QACjE,8KAA8K;QAC9K,EAAE;QACF,oBAAoB;KACpB,CAAC;IAEF,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,aAAa,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxD,KAAK,CAAC,IAAI,CAAC,oBAAoB,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;QAC7E,KAAK,CAAC,IAAI,CAAC,iBAAiB,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACpE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAClC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CACxB;AAED,SAAS,SAAS,CAAC,KAAa,EAAU;IACzC,OAAO,KAAK;SACV,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAAA,CAC1B","sourcesContent":["import type { Skill } from \"./types.ts\";\n\nexport function formatSkillsForSystemPrompt(skills: Skill[]): string {\n\tconst visibleSkills = skills.filter((skill) => !skill.disableModelInvocation);\n\tif (visibleSkills.length === 0) return \"\";\n\n\tconst lines = [\n\t\t\"The following skills provide specialized instructions for specific tasks.\",\n\t\t\"Read the full skill file when the task matches its description.\",\n\t\t\"When a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\",\n\t\t\"\",\n\t\t\"<available_skills>\",\n\t];\n\n\tfor (const skill of visibleSkills) {\n\t\tlines.push(\" <skill>\");\n\t\tlines.push(` <name>${escapeXml(skill.name)}</name>`);\n\t\tlines.push(` <description>${escapeXml(skill.description)}</description>`);\n\t\tlines.push(` <location>${escapeXml(skill.filePath)}</location>`);\n\t\tlines.push(\" </skill>\");\n\t}\n\n\tlines.push(\"</available_skills>\");\n\treturn lines.join(\"\\n\");\n}\n\nfunction escapeXml(value: string): string {\n\treturn value\n\t\t.replace(/&/g, \"&amp;\")\n\t\t.replace(/</g, \"&lt;\")\n\t\t.replace(/>/g, \"&gt;\")\n\t\t.replace(/\"/g, \"&quot;\")\n\t\t.replace(/'/g, \"&apos;\");\n}\n"]}
1
+ {"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/harness/system-prompt.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,2BAA2B,CAAC,MAAe;IAC1D,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC9E,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE1C,MAAM,KAAK,GAAG;QACb,2EAA2E;QAC3E,iEAAiE;QACjE,8KAA8K;QAC9K,EAAE;QACF,oBAAoB;KACpB,CAAC;IAEF,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,aAAa,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxD,KAAK,CAAC,IAAI,CAAC,oBAAoB,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;QAC7E,KAAK,CAAC,IAAI,CAAC,iBAAiB,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACpE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAClC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC/B,OAAO,KAAK;SACV,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC3B,CAAC","sourcesContent":["import type { Skill } from \"./types.ts\";\n\nexport function formatSkillsForSystemPrompt(skills: Skill[]): string {\n\tconst visibleSkills = skills.filter((skill) => !skill.disableModelInvocation);\n\tif (visibleSkills.length === 0) return \"\";\n\n\tconst lines = [\n\t\t\"The following skills provide specialized instructions for specific tasks.\",\n\t\t\"Read the full skill file when the task matches its description.\",\n\t\t\"When a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\",\n\t\t\"\",\n\t\t\"<available_skills>\",\n\t];\n\n\tfor (const skill of visibleSkills) {\n\t\tlines.push(\" <skill>\");\n\t\tlines.push(` <name>${escapeXml(skill.name)}</name>`);\n\t\tlines.push(` <description>${escapeXml(skill.description)}</description>`);\n\t\tlines.push(` <location>${escapeXml(skill.filePath)}</location>`);\n\t\tlines.push(\" </skill>\");\n\t}\n\n\tlines.push(\"</available_skills>\");\n\treturn lines.join(\"\\n\");\n}\n\nfunction escapeXml(value: string): string {\n\treturn value\n\t\t.replace(/&/g, \"&amp;\")\n\t\t.replace(/</g, \"&lt;\")\n\t\t.replace(/>/g, \"&gt;\")\n\t\t.replace(/\"/g, \"&quot;\")\n\t\t.replace(/'/g, \"&apos;\");\n}\n"]}