pinokiod 6.0.99 → 6.0.100

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "6.0.99",
3
+ "version": "6.0.100",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: pinokio
3
- description: Use pterm to discover apps, ensure they are running, and execute API requests with generated-once reusable clients.
3
+ description: Discover, launch, and use locally installed apps for the current task.
4
4
  ---
5
5
 
6
6
  # Pinokio Runtime Skill (pterm-first)
@@ -706,43 +706,101 @@ const createTerminalSessionHelpers = ({ kernel, fs, path, os, crypto }) => {
706
706
  return `${lines.join("\n").trim()}\n`
707
707
  }
708
708
 
709
- const buildCodexSelectedSkillMarkdown = (mergedBody) => {
710
- const body = String(mergedBody || "").trim()
711
- const lines = [
712
- "---",
713
- "name: Pinokio Selected Skills",
714
- "description: Session-specific skill bundle generated from the skills selected in Pinokio.",
715
- "tags:",
716
- "- pinokio",
717
- "- session",
718
- "- selected-skills",
719
- "---",
720
- "",
721
- body
722
- ]
723
- return `${lines.join("\n").trim()}\n`
709
+ const parseSimpleFrontmatter = (content) => {
710
+ const normalized = String(content || "").replace(/\r\n/g, "\n")
711
+ if (!normalized.startsWith("---\n")) {
712
+ return {
713
+ frontmatter: null
714
+ }
715
+ }
716
+ const end = normalized.indexOf("\n---\n", 4)
717
+ if (end === -1) {
718
+ return {
719
+ frontmatter: null
720
+ }
721
+ }
722
+ const rawFrontmatter = normalized.slice(4, end)
723
+ const lines = rawFrontmatter.split("\n")
724
+ const data = {}
725
+ let currentArrayKey = null
726
+ for (const line of lines) {
727
+ if (/^\s*-\s+/.test(line) && currentArrayKey) {
728
+ if (!Array.isArray(data[currentArrayKey])) {
729
+ data[currentArrayKey] = []
730
+ }
731
+ data[currentArrayKey].push(line.replace(/^\s*-\s+/, "").trim())
732
+ continue
733
+ }
734
+ currentArrayKey = null
735
+ const match = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(line)
736
+ if (!match) {
737
+ continue
738
+ }
739
+ const [, key, value] = match
740
+ if (value === "") {
741
+ data[key] = []
742
+ currentArrayKey = key
743
+ } else {
744
+ data[key] = value.trim()
745
+ }
746
+ }
747
+ return {
748
+ frontmatter: data
749
+ }
724
750
  }
725
751
 
726
- const ensureCodexSelectedSkillFrontmatter = async (sessionCwd) => {
727
- if (typeof sessionCwd !== "string" || sessionCwd.trim().length === 0) {
728
- return
729
- }
730
- const codexSkillPath = path.resolve(sessionCwd, ".agents", "skills", "pinokio-selected", "SKILL.md")
731
- let existing = ""
732
- try {
733
- existing = await fs.promises.readFile(codexSkillPath, "utf8")
734
- } catch (error) {
735
- if (error && error.code === "ENOENT") {
736
- return
752
+ const buildCodexWorkspaceSkillMarkdown = (mergedBody, selectedSkills) => {
753
+ const body = String(mergedBody || "").trim()
754
+ const normalizedSkills = Array.isArray(selectedSkills) ? selectedSkills : []
755
+ const primary = normalizedSkills.find((skill) => skill && skill.id === "pinokio") || normalizedSkills[0] || null
756
+ const descriptions = []
757
+ const descriptionSet = new Set()
758
+ const tags = []
759
+ const tagSet = new Set()
760
+ const addDescription = (value) => {
761
+ const text = typeof value === "string" ? value.trim() : ""
762
+ if (!text) return
763
+ const key = text.toLowerCase()
764
+ if (descriptionSet.has(key)) return
765
+ descriptionSet.add(key)
766
+ descriptions.push(text)
767
+ }
768
+ const addTags = (value) => {
769
+ if (!Array.isArray(value)) return
770
+ for (const entry of value) {
771
+ const text = typeof entry === "string" ? entry.trim() : ""
772
+ if (!text) continue
773
+ const key = text.toLowerCase()
774
+ if (tagSet.has(key)) continue
775
+ tagSet.add(key)
776
+ tags.push(text)
777
+ }
778
+ }
779
+ if (primary && primary.frontmatter) {
780
+ addDescription(primary.frontmatter.description)
781
+ addTags(primary.frontmatter.tags)
782
+ }
783
+ for (const skill of normalizedSkills) {
784
+ if (!skill || !skill.frontmatter || skill === primary) {
785
+ continue
737
786
  }
738
- throw error
787
+ addDescription(skill.frontmatter.description)
788
+ addTags(skill.frontmatter.tags)
739
789
  }
740
- const normalized = String(existing || "").replace(/\r\n/g, "\n")
741
- if (normalized.startsWith("---\n")) {
742
- return
790
+ if (!tagSet.has("selected-skills")) {
791
+ tags.push("selected-skills")
743
792
  }
744
- const wrapped = buildCodexSelectedSkillMarkdown(normalized)
745
- await fs.promises.writeFile(codexSkillPath, wrapped, "utf8")
793
+ const lines = [
794
+ "---",
795
+ "name: pinokio-workspace",
796
+ `description: ${descriptions.join(" Also: ") || "Workspace skill bundle generated from the skills selected in Pinokio."}`,
797
+ "tags:"
798
+ ]
799
+ for (const tag of tags) {
800
+ lines.push(`- ${tag}`)
801
+ }
802
+ lines.push("---", "", body)
803
+ return `${lines.join("\n").trim()}\n`
746
804
  }
747
805
 
748
806
  const materializeTerminalSkillContext = async (sessionCwd, providerKey, selectedSkills) => {
@@ -772,7 +830,8 @@ const createTerminalSessionHelpers = ({ kernel, fs, path, os, crypto }) => {
772
830
  id: skill.id,
773
831
  label: skill.label,
774
832
  file: skill.file,
775
- body
833
+ body,
834
+ ...parseSimpleFrontmatter(body)
776
835
  })
777
836
  }
778
837
 
@@ -790,13 +849,17 @@ const createTerminalSessionHelpers = ({ kernel, fs, path, os, crypto }) => {
790
849
  await fs.promises.writeFile(activePath, merged, "utf8")
791
850
 
792
851
  if (providerKey === "codex") {
793
- const codexSkillDir = path.resolve(sessionCwd, ".agents", "skills", "pinokio-selected")
852
+ const singleSkill = skillsWithBody.length === 1 ? skillsWithBody[0] : null
853
+ const workspaceSkillId = singleSkill ? singleSkill.id : "pinokio-workspace"
854
+ const codexSkillDir = path.resolve(sessionCwd, ".agents", "skills", workspaceSkillId)
794
855
  await fs.promises.mkdir(codexSkillDir, { recursive: true })
795
856
  const codexSkillPath = path.resolve(codexSkillDir, "SKILL.md")
796
- const codexSkillBody = buildCodexSelectedSkillMarkdown(merged)
857
+ const codexSkillBody = singleSkill
858
+ ? `${String(singleSkill.body || "").trim()}\n`
859
+ : buildCodexWorkspaceSkillMarkdown(merged, skillsWithBody)
797
860
  await fs.promises.writeFile(codexSkillPath, codexSkillBody, "utf8")
798
861
  const agentsPath = path.resolve(sessionCwd, "AGENTS.md")
799
- await fs.promises.writeFile(agentsPath, "# Pinokio session instructions\n\nUse the `pinokio-selected` skill from `.agents/skills/pinokio-selected/SKILL.md` for this workspace.\n", "utf8")
862
+ await fs.promises.writeFile(agentsPath, `# Pinokio session instructions\n\nUse the \`${workspaceSkillId}\` skill from \`.agents/skills/${workspaceSkillId}/SKILL.md\` for this workspace.\n`, "utf8")
800
863
  } else if (providerKey === "claude") {
801
864
  const claudePath = path.resolve(sessionCwd, "CLAUDE.md")
802
865
  await fs.promises.writeFile(claudePath, merged, "utf8")