@my-life-buddies/buddy-creator-skill 1.6.0

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 (159) hide show
  1. package/INSTALL.md +25 -0
  2. package/PATCHES.md +57 -0
  3. package/README.md +76 -0
  4. package/SKILL.md +78 -0
  5. package/THIRD_PARTY_NOTICES.md +154 -0
  6. package/agents/openai.yaml +4 -0
  7. package/assets/licenses/bail.txt +26 -0
  8. package/assets/licenses/ccount.txt +26 -0
  9. package/assets/licenses/character-entities-html4.txt +26 -0
  10. package/assets/licenses/character-entities-legacy.txt +26 -0
  11. package/assets/licenses/character-entities.txt +26 -0
  12. package/assets/licenses/character-reference-invalid.txt +26 -0
  13. package/assets/licenses/comma-separated-tokens.txt +26 -0
  14. package/assets/licenses/debug.txt +24 -0
  15. package/assets/licenses/decode-named-character-reference.txt +26 -0
  16. package/assets/licenses/dequal.txt +25 -0
  17. package/assets/licenses/devlop.txt +26 -0
  18. package/assets/licenses/escape-string-regexp.txt +13 -0
  19. package/assets/licenses/estree-util-is-identifier-name.txt +26 -0
  20. package/assets/licenses/extend.txt +27 -0
  21. package/assets/licenses/hast-util-to-jsx-runtime.txt +26 -0
  22. package/assets/licenses/hast-util-whitespace.txt +26 -0
  23. package/assets/licenses/html-url-attributes.txt +25 -0
  24. package/assets/licenses/inline-style-parser.txt +13 -0
  25. package/assets/licenses/is-alphabetical.txt +26 -0
  26. package/assets/licenses/is-alphanumerical.txt +26 -0
  27. package/assets/licenses/is-decimal.txt +26 -0
  28. package/assets/licenses/is-hexadecimal.txt +26 -0
  29. package/assets/licenses/is-plain-obj.txt +13 -0
  30. package/assets/licenses/longest-streak.txt +26 -0
  31. package/assets/licenses/markdown-table.txt +26 -0
  32. package/assets/licenses/mdast-util-find-and-replace.txt +26 -0
  33. package/assets/licenses/mdast-util-from-markdown.txt +26 -0
  34. package/assets/licenses/mdast-util-gfm-autolink-literal.txt +26 -0
  35. package/assets/licenses/mdast-util-gfm-footnote.txt +26 -0
  36. package/assets/licenses/mdast-util-gfm-strikethrough.txt +26 -0
  37. package/assets/licenses/mdast-util-gfm-table.txt +26 -0
  38. package/assets/licenses/mdast-util-gfm-task-list-item.txt +26 -0
  39. package/assets/licenses/mdast-util-gfm.txt +26 -0
  40. package/assets/licenses/mdast-util-mdx-expression.txt +26 -0
  41. package/assets/licenses/mdast-util-mdx-jsx.txt +26 -0
  42. package/assets/licenses/mdast-util-mdxjs-esm.txt +26 -0
  43. package/assets/licenses/mdast-util-phrasing.txt +27 -0
  44. package/assets/licenses/mdast-util-to-hast.txt +26 -0
  45. package/assets/licenses/mdast-util-to-markdown.txt +26 -0
  46. package/assets/licenses/mdast-util-to-string.txt +26 -0
  47. package/assets/licenses/micromark-core-commonmark.txt +26 -0
  48. package/assets/licenses/micromark-extension-gfm-autolink-literal.txt +26 -0
  49. package/assets/licenses/micromark-extension-gfm-footnote.txt +26 -0
  50. package/assets/licenses/micromark-extension-gfm-strikethrough.txt +26 -0
  51. package/assets/licenses/micromark-extension-gfm-table.txt +26 -0
  52. package/assets/licenses/micromark-extension-gfm-tagfilter.txt +26 -0
  53. package/assets/licenses/micromark-extension-gfm-task-list-item.txt +26 -0
  54. package/assets/licenses/micromark-extension-gfm.txt +26 -0
  55. package/assets/licenses/micromark-factory-destination.txt +26 -0
  56. package/assets/licenses/micromark-factory-label.txt +26 -0
  57. package/assets/licenses/micromark-factory-space.txt +26 -0
  58. package/assets/licenses/micromark-factory-title.txt +26 -0
  59. package/assets/licenses/micromark-factory-whitespace.txt +26 -0
  60. package/assets/licenses/micromark-util-character.txt +26 -0
  61. package/assets/licenses/micromark-util-chunked.txt +26 -0
  62. package/assets/licenses/micromark-util-classify-character.txt +26 -0
  63. package/assets/licenses/micromark-util-combine-extensions.txt +26 -0
  64. package/assets/licenses/micromark-util-decode-numeric-character-reference.txt +26 -0
  65. package/assets/licenses/micromark-util-decode-string.txt +26 -0
  66. package/assets/licenses/micromark-util-encode.txt +26 -0
  67. package/assets/licenses/micromark-util-html-tag-name.txt +26 -0
  68. package/assets/licenses/micromark-util-normalize-identifier.txt +26 -0
  69. package/assets/licenses/micromark-util-resolve-all.txt +26 -0
  70. package/assets/licenses/micromark-util-sanitize-uri.txt +26 -0
  71. package/assets/licenses/micromark-util-subtokenize.txt +26 -0
  72. package/assets/licenses/micromark-util-symbol.txt +26 -0
  73. package/assets/licenses/micromark-util-types.txt +26 -0
  74. package/assets/licenses/micromark.txt +26 -0
  75. package/assets/licenses/ms.txt +25 -0
  76. package/assets/licenses/parse-entities.txt +26 -0
  77. package/assets/licenses/phosphor-icons--react.txt +25 -0
  78. package/assets/licenses/property-information.txt +26 -0
  79. package/assets/licenses/react-dom.txt +25 -0
  80. package/assets/licenses/react-markdown.txt +25 -0
  81. package/assets/licenses/react.txt +25 -0
  82. package/assets/licenses/remark-gfm.txt +26 -0
  83. package/assets/licenses/remark-parse.txt +25 -0
  84. package/assets/licenses/remark-rehype.txt +26 -0
  85. package/assets/licenses/remark-stringify.txt +25 -0
  86. package/assets/licenses/scheduler.txt +25 -0
  87. package/assets/licenses/space-separated-tokens.txt +26 -0
  88. package/assets/licenses/stringify-entities.txt +26 -0
  89. package/assets/licenses/style-to-js.txt +26 -0
  90. package/assets/licenses/style-to-object.txt +26 -0
  91. package/assets/licenses/trim-lines.txt +26 -0
  92. package/assets/licenses/trough.txt +25 -0
  93. package/assets/licenses/types--debug.txt +25 -0
  94. package/assets/licenses/types--estree-jsx.txt +25 -0
  95. package/assets/licenses/types--estree.txt +25 -0
  96. package/assets/licenses/types--hast.txt +25 -0
  97. package/assets/licenses/types--mdast.txt +25 -0
  98. package/assets/licenses/types--ms.txt +25 -0
  99. package/assets/licenses/types--unist.txt +25 -0
  100. package/assets/licenses/ungap--structured-clone.txt +19 -0
  101. package/assets/licenses/unified.txt +25 -0
  102. package/assets/licenses/unist-util-is.txt +26 -0
  103. package/assets/licenses/unist-util-position.txt +26 -0
  104. package/assets/licenses/unist-util-stringify-position.txt +26 -0
  105. package/assets/licenses/unist-util-visit-parents.txt +26 -0
  106. package/assets/licenses/unist-util-visit.txt +26 -0
  107. package/assets/licenses/vfile-message.txt +26 -0
  108. package/assets/licenses/vfile.txt +25 -0
  109. package/assets/licenses/zwitch.txt +26 -0
  110. package/assets/preview/assets/index-B5VmkoSx.js +39 -0
  111. package/assets/preview/assets/index-DWKP6b-3.css +4 -0
  112. package/assets/preview/brand-logo.png +0 -0
  113. package/assets/preview/brand.css +100 -0
  114. package/assets/preview/index.html +7 -0
  115. package/assets/preview/reader.css +165 -0
  116. package/assets/preview/reader.js +135 -0
  117. package/assets/preview/widgets.css +1 -0
  118. package/assets/preview/widgets.js +168 -0
  119. package/assets/widget-reference/conversation.png +0 -0
  120. package/assets/widget-reference/expanded.png +0 -0
  121. package/assets/widget-v2/app.js +62 -0
  122. package/assets/widget-v2/style.css +1 -0
  123. package/assets/widget-v3/app.js +65 -0
  124. package/assets/widget-v3/style.css +103 -0
  125. package/assets/widget-v4/app.js +66 -0
  126. package/assets/widget-v4/style.css +187 -0
  127. package/package.json +37 -0
  128. package/references/artifact-schema.md +70 -0
  129. package/references/catalog.json +401 -0
  130. package/references/cli-workflow.md +15 -0
  131. package/references/definition.md +24 -0
  132. package/references/dialogue-examples.md +133 -0
  133. package/references/host-guide.md +219 -0
  134. package/references/interview.md +235 -0
  135. package/references/knowledge.md +40 -0
  136. package/references/methods-protocol.md +60 -0
  137. package/references/methods.md +98 -0
  138. package/references/opening.md +14 -0
  139. package/references/preview-panel.md +66 -0
  140. package/references/recovery.md +46 -0
  141. package/references/service.md +76 -0
  142. package/references/widgets-protocol.md +83 -0
  143. package/references/widgets.md +99 -0
  144. package/scripts/buddy.py +108 -0
  145. package/scripts/buddy_client.py +67 -0
  146. package/scripts/buddy_core.py +908 -0
  147. package/scripts/completion.py +296 -0
  148. package/scripts/interview.py +218 -0
  149. package/scripts/methods.py +181 -0
  150. package/scripts/preview.py +631 -0
  151. package/scripts/preview_panel.py +80 -0
  152. package/scripts/sources.py +239 -0
  153. package/scripts/widget_render.py +66 -0
  154. package/scripts/widget_render_v1.py +176 -0
  155. package/scripts/widget_render_v2.py +98 -0
  156. package/scripts/widget_render_v3.py +86 -0
  157. package/scripts/widget_render_v4.py +121 -0
  158. package/scripts/widgets.py +227 -0
  159. package/version.json +8 -0
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env python3
2
+ """Run Buddy Creator Skill using only the Python standard library."""
3
+ import argparse
4
+ import json
5
+ import os
6
+ import re
7
+ import sys
8
+ from pathlib import Path
9
+
10
+ if sys.version_info < (3, 9):
11
+ print(json.dumps({'ok': False, 'error': {'code': 'PYTHON_VERSION', 'message': '需要 Python 3.9 或更高版本;无需 Node、npm 或 pip。'}}, ensure_ascii=False))
12
+ sys.exit(1)
13
+ if hasattr(sys.stdout, 'reconfigure'):
14
+ sys.stdout.reconfigure(encoding='utf-8')
15
+ if hasattr(sys.stderr, 'reconfigure'):
16
+ sys.stderr.reconfigure(encoding='utf-8')
17
+
18
+ import buddy_core as core
19
+
20
+
21
+ def parse_input(path):
22
+ if path == '-' and sys.stdin.isatty():
23
+ raise core.BuddyError('INPUT_TTY', '请求 JSON 不接受交互式 TTY 输入;请用 --input <UTF-8 JSON文件>,或通过非 TTY 管道提交 --input -。无需发送 Ctrl-D。')
24
+ try:
25
+ raw = sys.stdin.read() if path == '-' else Path(path).expanduser().read_text(encoding='utf-8')
26
+ return json.loads(raw)
27
+ except json.JSONDecodeError as error:
28
+ raise core.BuddyError('INPUT_JSON', '请求 JSON 格式无效。', {'line': error.lineno, 'column': error.colno}) from error
29
+ except (OSError, ValueError) as error:
30
+ raise core.BuddyError('INPUT_JSON', '无法读取请求 JSON;--input 使用 UTF-8 文件路径或 - 表示标准输入。') from error
31
+
32
+
33
+ def main():
34
+ parser = argparse.ArgumentParser(description='Buddy Creator Skill:宿主采访、Python 本地保存与只读预览。')
35
+ parser.add_argument('--version', action='version', version=core.METADATA['displayName'] + ' ' + core.METADATA['version'])
36
+ sub = parser.add_subparsers(dest='command', required=True)
37
+ opened = sub.add_parser('open', help='创建或恢复 Buddy 项目')
38
+ opened.add_argument('--creation-key')
39
+ opened.add_argument('--workspace')
40
+ opened.add_argument('--context', help='可选的初始背景 JSON 文件;不是采访回答或确认')
41
+ opened.add_argument('--no-browser', action='store_true', help='由宿主打开预览,不调用系统浏览器(默认行为)')
42
+ call = sub.add_parser('call', help='提交协议请求')
43
+ call.add_argument('--workspace', required=True)
44
+ call.add_argument('--input', default='-')
45
+ panel = sub.add_parser('preview-panel', help='记录宿主观察到的面板状态与一次性重开提醒;不改变采访进度')
46
+ panel.add_argument('--workspace', required=True)
47
+ panel.add_argument('--input', default='-', help='包含 action 的 JSON 文件或非 TTY 标准输入')
48
+ for name in ['serve', 'status']:
49
+ command = sub.add_parser(name)
50
+ command.add_argument('--workspace', required=True)
51
+ args = parser.parse_args()
52
+ if args.command == 'serve':
53
+ import preview
54
+ preview.serve(Path(args.workspace).expanduser().resolve())
55
+ return
56
+ if args.command == 'open':
57
+ initial_context = parse_input(args.context) if args.context else None
58
+ if args.context and initial_context is None:
59
+ raise core.BuddyError('INITIAL_CONTEXT_SCHEMA', '初始背景必须为 JSON 对象,不能为 null。')
60
+ workspace, state = core.open_workspace(args.creation_key, args.workspace, initial_context)
61
+ import preview
62
+ try:
63
+ endpoint = preview.start(workspace)
64
+ except Exception as error:
65
+ endpoint = {'status': 'unavailable', 'message': str(error), 'recovery': '项目已经保存。允许本地端口后重试同一 open;不要更换 creation-key。'}
66
+ directive = 'continue_turn' if state.get('pendingTurnId') else ('prepare_opening' if core.needs_opening(state) else 'present_delivery')
67
+ result = {'workspace': str(workspace), 'buddyId': state['buddyId'], 'preview': endpoint, 'delivery': None if directive == 'prepare_opening' else state['deliveries'].get(state.get('currentDeliveryId')), 'directive': directive, 'context': core.context(workspace, state), 'entrypointCommand': {'executable': sys.executable, 'args': [str(Path(__file__).resolve())]}}
68
+ elif args.command == 'status':
69
+ workspace = Path(args.workspace).expanduser().resolve()
70
+ with core.workspace_lock(workspace):
71
+ state = core.load(workspace)
72
+ import preview
73
+ result = {'workspace': str(workspace), 'context': core.context(workspace, state), 'snapshot': preview.snapshot(workspace, state)}
74
+ elif args.command == 'preview-panel':
75
+ import preview_panel
76
+ result = preview_panel.call(args.workspace, parse_input(args.input))
77
+ else:
78
+ result = core.call(args.workspace, parse_input(args.input))
79
+ if args.command in ('open', 'status'):
80
+ import completion
81
+ completion.return_to_caller(workspace, state, result)
82
+ print(json.dumps(dict(ok=True, product=core.METADATA['displayName'], version=core.METADATA['version'], **result), ensure_ascii=False, indent=2, allow_nan=False), flush=True)
83
+
84
+
85
+ def cli():
86
+ try:
87
+ try:
88
+ main()
89
+ return 0
90
+ except core.BuddyError as error:
91
+ print(json.dumps({'ok': False, 'error': {'code': error.code, 'message': str(error), 'details': error.details}}, ensure_ascii=False, indent=2), flush=True)
92
+ except BrokenPipeError:
93
+ raise
94
+ except Exception as error:
95
+ match = re.match(r'^([A-Z][A-Z0-9_]+):\s*(.*)', str(error), re.DOTALL)
96
+ code, message = match.groups() if match else ('UNEXPECTED_ERROR', str(error))
97
+ print(json.dumps({'ok': False, 'error': {'code': code, 'message': message, 'recovery': '已提交的原话和历史版本仍保留。读取 status 或 turn_continue 恢复,勿创建重复项目。'}}, ensure_ascii=False, indent=2), flush=True)
98
+ return 1
99
+ except BrokenPipeError:
100
+ # Prevent a second failure when Python flushes stdout during shutdown.
101
+ with open(os.devnull, 'w') as sink:
102
+ os.dup2(sink.fileno(), sys.stdout.fileno())
103
+ print(json.dumps({'error': {'code': 'OUTPUT_CLOSED', 'message': '回执输出管道已关闭,操作可能已经保存。请先读取 status 或 turn_continue 核对结果;不要创建新回合重复提交。'}}, ensure_ascii=False), file=sys.stderr, flush=True)
104
+ return 1
105
+
106
+
107
+ if __name__ == '__main__':
108
+ sys.exit(cli())
@@ -0,0 +1,67 @@
1
+ """A workspace-bound, stdlib-only client for host-authored Creator requests."""
2
+ import json
3
+ import os
4
+ from pathlib import Path
5
+ import subprocess
6
+ import sys
7
+
8
+ from buddy_core import BuddyError
9
+
10
+
11
+ class BuddyClient:
12
+ def __init__(self, workspace, python=None, timeout=60):
13
+ self.workspace = str(Path(workspace).expanduser().resolve())
14
+ self.command = [python or sys.executable, '-B', str(Path(__file__).with_name('buddy.py'))]
15
+ self.timeout = timeout
16
+ self.context = None
17
+
18
+ def _run(self, command, payload=None):
19
+ args = self.command + [command, '--workspace', self.workspace]
20
+ raw = None
21
+ if payload is not None:
22
+ args += ['--input', '-']
23
+ raw = json.dumps(payload, ensure_ascii=False, allow_nan=False)
24
+ try:
25
+ process = subprocess.run(args, input=raw, stdin=subprocess.DEVNULL if raw is None else None,
26
+ capture_output=True, encoding='utf-8', timeout=self.timeout,
27
+ env={**os.environ, 'PYTHONDONTWRITEBYTECODE': '1'})
28
+ except (OSError, subprocess.TimeoutExpired) as error:
29
+ raise BuddyError('CLIENT_TRANSPORT', '未取得 Creator 回执;先用 status 或 turn_continue 核对结果,不自动重试写入。') from error
30
+ try:
31
+ result = json.loads(process.stdout)
32
+ except ValueError as error:
33
+ raise BuddyError('CLIENT_RESPONSE', 'Creator 回执不是完整 JSON;先核对已保存状态,不创建新回合重试。',
34
+ {'exitCode': process.returncode}) from error
35
+ if isinstance(result, dict) and result.get('ok') is False and isinstance(result.get('error'), dict):
36
+ error = result['error']
37
+ raise BuddyError(error['code'], error['message'], error.get('details'))
38
+ if process.returncode or not isinstance(result, dict) or result.get('ok') is not True:
39
+ raise BuddyError('CLIENT_RESPONSE', 'Creator 未返回成功回执;先核对已保存状态。', {'exitCode': process.returncode})
40
+ if 'context' in result:
41
+ self.context = result['context']
42
+ return result
43
+
44
+ def status(self):
45
+ return self._run('status')
46
+
47
+ def call(self, payload):
48
+ # No automatic retries: the host retains the exact clientKey/turnId and payload.
49
+ return self._run('call', payload)
50
+
51
+ def _object(self, collection, object_id):
52
+ if self.context is None:
53
+ raise BuddyError('CLIENT_CONTEXT', '先调用 status 或保存本轮输入,再从返回的版本生成引用。')
54
+ item = self.context['state'][collection].get(object_id)
55
+ if item is None:
56
+ raise BuddyError('CLIENT_REFERENCE', '当前回执中没有此对象,请核对 ID。', {'id': object_id})
57
+ return item
58
+
59
+ def artifact_ref(self, object_id):
60
+ item = self._object('artifacts', object_id)
61
+ return {'type': 'artifact', 'id': object_id, 'hash': item['hash']}
62
+
63
+ def input_ref(self, input_id, quote):
64
+ item = self._object('inputs', input_id)
65
+ if not isinstance(quote, str) or not quote.strip() or quote not in item['raw']:
66
+ raise BuddyError('EVIDENCE_QUOTE', '引用必须是该输入中的非空精确原话。', {'id': input_id})
67
+ return {'type': 'input', 'id': input_id, 'hash': item['hash'], 'quote': quote}