@mawaru/sdk 0.40.0 → 0.41.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 (56) hide show
  1. package/_schemas/graph.ts +0 -5
  2. package/_schemas/human-manifest.test.ts +39 -101
  3. package/_schemas/human-manifest.ts +25 -152
  4. package/_schemas/port-spec.test.ts +33 -92
  5. package/_schemas/port-spec.ts +35 -44
  6. package/dist/_cli/login.js +15 -1
  7. package/dist/_cli/previewApi.d.ts +1 -1
  8. package/dist/_cli/previewCommand.d.ts +0 -8
  9. package/dist/_cli/previewCommand.js +37 -95
  10. package/dist/_cli/previewFiles.d.ts +1 -2
  11. package/dist/_cli/previewFiles.js +18 -42
  12. package/dist/_schemas/graph.d.ts +0 -15
  13. package/dist/_schemas/graph.js +0 -5
  14. package/dist/_schemas/human-manifest.d.ts +6 -24
  15. package/dist/_schemas/human-manifest.js +24 -116
  16. package/dist/_schemas/port-spec.d.ts +1 -4
  17. package/dist/_schemas/port-spec.js +25 -34
  18. package/dist/cli.js +1 -2
  19. package/dist/typegen.d.ts +2 -2
  20. package/dist/typegen.js +21 -21
  21. package/dist/validate.js +9 -7
  22. package/dist/views/_humanProps.d.ts +10 -0
  23. package/dist/views/_humanProps.js +11 -0
  24. package/dist/views/{index.d.ts → components.d.ts} +0 -1
  25. package/dist/views/components.js +12 -0
  26. package/dist/views/host.d.ts +8 -3
  27. package/dist/views/host.js +5 -5
  28. package/dist/views/human.d.ts +49 -68
  29. package/dist/views/human.js +5 -6
  30. package/dist/views/protocol.d.ts +13 -3
  31. package/dist/views/protocol.js +2 -2
  32. package/dist/views/runtime.d.ts +2 -3
  33. package/dist/views/runtime.js +24 -24
  34. package/dist/views/sample.d.ts +22 -0
  35. package/dist/views/sample.js +38 -0
  36. package/docs/development.md +30 -31
  37. package/package.json +5 -1
  38. package/skills/create-loop/SKILL.md +3 -2
  39. package/templates/CLAUDE.md +2 -0
  40. package/views/_humanProps.ts +27 -0
  41. package/views/components.ts +16 -0
  42. package/views/host.ts +9 -5
  43. package/views/human.ts +71 -79
  44. package/views/protocol.ts +29 -6
  45. package/views/runtime.tsx +36 -45
  46. package/views/sample.tsx +94 -0
  47. package/dist/_cli/openBrowser.d.ts +0 -1
  48. package/dist/_cli/openBrowser.js +0 -15
  49. package/dist/views/_approval/ApprovalBar.d.ts +0 -20
  50. package/dist/views/_approval/ApprovalBar.js +0 -74
  51. package/dist/views/_approvalActions.d.ts +0 -18
  52. package/dist/views/_approvalActions.js +0 -10
  53. package/dist/views/index.js +0 -12
  54. package/views/_approval/ApprovalBar.tsx +0 -239
  55. package/views/_approvalActions.tsx +0 -31
  56. package/views/index.ts +0 -16
@@ -1,239 +0,0 @@
1
- import { type ReactNode, useState } from "react"
2
- import { useApprovalActions } from "../_approvalActions.js"
3
- import type { ApprovalViewContext } from "../human.js"
4
-
5
- // 承認バー(承認画面の下の帯)。ビューが自分で置く部品で、内蔵の標準ビューも同じものを使う
6
- // (docs/tasks/wip/承認ビューの顧客repo配置.md の「承認バーもビューが描く」)。
7
- // 材料は ctx.decision、操作は useApprovalActions()。送信中とエラーは decide の結果からここで持つ
8
-
9
- const errorMessage = (err: unknown) =>
10
- err instanceof Error ? err.message : "送信に失敗しました"
11
-
12
- /**
13
- * 承認バー。書類の領域の下に貼り付く(`position: sticky; bottom: 0`)。外側を `minHeight: 100%` の縦の flex にして
14
- * 中身を `flex: 1` にすると、中身が短くても下端に来る。
15
- */
16
- export const ApprovalBar = <TOut = unknown>({
17
- ctx,
18
- label,
19
- disabled = false,
20
- output,
21
- value,
22
- children,
23
- }: {
24
- /** ビューが受け取った ctx */
25
- ctx: ApprovalViewContext<unknown>
26
- /** 承認ボタンの文言(省略時は「承認して〈次のノード〉へ」) */
27
- label?: string
28
- /** 承認ボタンを押せない */
29
- disabled?: boolean
30
- /** 承認したとき approve に流す値(宣言の outputs.approve の形。省略時は value)。`<ApprovalBar<Approve> …>` で型を検査できる */
31
- output?: TOut
32
- /** 今の値(ビューで直した値。in の形。省略時は ctx.output)。型の合う追加の出口にはこれが流れる */
33
- value?: unknown
34
- /** バーの左側に足すもの */
35
- children?: ReactNode
36
- }) => {
37
- const actions = useApprovalActions()
38
- const [sending, setSending] = useState(false)
39
- const [error, setError] = useState<string | null>(null)
40
- const { phase, decision } = ctx
41
- const current = value === undefined ? ctx.output : value
42
- const approveValue = output === undefined ? current : output
43
-
44
- const send = (request: Promise<void>) => {
45
- setSending(true)
46
- setError(null)
47
- request
48
- .catch((err: unknown) => setError(errorMessage(err)))
49
- .finally(() => setSending(false))
50
- }
51
- const open = (request: Promise<void>) =>
52
- request.catch((err: unknown) => setError(errorMessage(err)))
53
-
54
- return (
55
- <div
56
- style={{
57
- position: "sticky",
58
- bottom: 0,
59
- zIndex: 1,
60
- flex: "none",
61
- display: "flex",
62
- alignItems: "center",
63
- gap: "var(--space-3)",
64
- padding: "var(--space-3) var(--space-6)",
65
- borderTop:
66
- phase === "waiting"
67
- ? "var(--border-w-strong) solid var(--human)"
68
- : "var(--border-w) solid var(--border)",
69
- background: "var(--surface)",
70
- }}
71
- >
72
- {phase === "waiting" ? (
73
- <>
74
- {/* 承認できない理由だけ出す(渡し先はボタンのラベルが言っている) */}
75
- {decision.otherAssignees && (
76
- <span style={{ fontSize: "var(--text-sm)", color: "var(--muted)" }}>
77
- <span style={{ color: "var(--ink)" }}>
78
- {decision.otherAssignees.join("・")}
79
- </span>
80
- {" さんの担当です — あなたは承認・差し戻しができません"}
81
- </span>
82
- )}
83
- {children}
84
- <div style={{ flex: 1 }} />
85
- {decision.progress && (
86
- // 全員の承認が要るときの進み具合。自分が承認済みなら残りを待つ
87
- <span
88
- style={{
89
- fontFamily: "var(--font-mono)",
90
- fontSize: "var(--text-xs)",
91
- color: "var(--muted)",
92
- whiteSpace: "nowrap",
93
- }}
94
- >
95
- {decision.progress.done}/{decision.progress.total}人 承認済み
96
- </span>
97
- )}
98
- {error && (
99
- <span role="alert" style={{ color: "var(--fail)" }}>
100
- {error}
101
- </span>
102
- )}
103
- {decision.exits.map((exit) => (
104
- <button
105
- key={exit.key}
106
- type="button"
107
- className="ghost"
108
- disabled={!decision.canDecide || sending}
109
- onClick={() =>
110
- exit.needsInput
111
- ? open(actions.openExitDialog(exit.key, current))
112
- : send(actions.decide(exit.key, current))
113
- }
114
- style={{ fontSize: "var(--text-sm)", whiteSpace: "nowrap" }}
115
- >
116
- {exit.name}
117
- </button>
118
- ))}
119
- {decision.rejectTargetName && (
120
- <button
121
- type="button"
122
- className="ghost"
123
- disabled={!decision.canDecide || sending}
124
- onClick={() => open(actions.openRejectDialog())}
125
- style={{ fontSize: "var(--text-sm)", whiteSpace: "nowrap" }}
126
- >
127
- AIへ差し戻す(reject)
128
- </button>
129
- )}
130
- <button
131
- type="button"
132
- className="primary"
133
- disabled={!decision.canDecide || sending || disabled}
134
- onClick={() => send(actions.decide("approve", approveValue))}
135
- style={{
136
- display: "flex",
137
- alignItems: "center",
138
- gap: "var(--space-2)",
139
- paddingLeft: "var(--space-5)",
140
- paddingRight: "var(--space-5)",
141
- whiteSpace: "nowrap",
142
- }}
143
- >
144
- {sending
145
- ? "承認しています…"
146
- : decision.progress?.approvedByMe
147
- ? "承認済み — 全員の承認待ち"
148
- : (label ?? `承認して${decision.approveTargetName ?? "次"}へ`)}
149
- <svg width="12" height="12" viewBox="0 0 16 16" aria-hidden="true">
150
- <path
151
- d="M4.5 3L12.5 8L4.5 13V3Z"
152
- style={{ fill: "var(--on-accent)" }}
153
- />
154
- </svg>
155
- </button>
156
- </>
157
- ) : phase === "rejected" ? (
158
- <>
159
- <svg
160
- width="14"
161
- height="14"
162
- viewBox="0 0 16 16"
163
- style={{ flex: "none" }}
164
- aria-hidden="true"
165
- >
166
- <rect
167
- x="3.5"
168
- y="7"
169
- width="9"
170
- height="6"
171
- rx="1.5"
172
- style={{ fill: "none", stroke: "var(--muted)", strokeWidth: 1.5 }}
173
- />
174
- <path
175
- d="M5.5 7V5.5C5.5 4 6.5 3 8 3C9.5 3 10.5 4 10.5 5.5V7"
176
- style={{ fill: "none", stroke: "var(--muted)", strokeWidth: 1.5 }}
177
- />
178
- </svg>
179
- <span style={{ fontSize: "var(--text-xs)", color: "var(--muted)" }}>
180
- 再実行が完了して新しい下書きが届くと、承認待ちに戻り通知されます
181
- </span>
182
- <div style={{ flex: 1 }} />
183
- <button
184
- type="button"
185
- className="ghost"
186
- disabled
187
- style={{
188
- fontSize: "var(--text-sm)",
189
- opacity: 0.5,
190
- whiteSpace: "nowrap",
191
- }}
192
- >
193
- 差し戻す(reject)
194
- </button>
195
- <button
196
- type="button"
197
- className="primary"
198
- disabled
199
- style={{ opacity: 0.5, whiteSpace: "nowrap" }}
200
- >
201
- 承認して次へ
202
- </button>
203
- </>
204
- ) : (
205
- <>
206
- <span
207
- style={{
208
- color:
209
- phase === "failed"
210
- ? "var(--fail)"
211
- : phase === "cancelled"
212
- ? "var(--muted)"
213
- : "var(--ok)",
214
- fontSize: "var(--text-sm)",
215
- }}
216
- >
217
- {phase === "failed" ? "✕" : phase === "cancelled" ? "◼" : "✓"}
218
- </span>
219
- <span style={{ fontSize: "var(--text-sm)", color: "var(--muted)" }}>
220
- {phase === "failed"
221
- ? (decision.failedReason ?? "この step は失敗しました")
222
- : phase === "cancelled"
223
- ? "キャンセル済み — この run は中断されました"
224
- : "対応済み — 承認して次のノードへ渡しました"}
225
- </span>
226
- <div style={{ flex: 1 }} />
227
- <button
228
- type="button"
229
- className="ghost"
230
- onClick={() => open(actions.close())}
231
- style={{ fontSize: "var(--text-sm)", whiteSpace: "nowrap" }}
232
- >
233
- run の進行を見る →
234
- </button>
235
- </>
236
- )}
237
- </div>
238
- )
239
- }
@@ -1,31 +0,0 @@
1
- import { createContext, useContext } from "react"
2
-
3
- // 承認ビューからホスト(mawaru の承認画面)に頼む口。提供(Provider)はホストと iframe の中の実行部分だけが使うので
4
- // host.ts から出し、ビューを書く人向けの approval.ts からは型と useApprovalActions だけを出す
5
-
6
- /**
7
- * ビューから承認画面の操作を頼む口。決定の送信はホストが行う。
8
- * ホストは、この step で・見ている人が決定できる(`ctx.decision.canDecide`)ときだけ受け、
9
- * `decide` はさらに人がビューの中で押した直後のときだけ受ける(開いただけで決定するビューは書けない)。
10
- */
11
- export type ApprovalActions = {
12
- /** 決定する。`port` は `approve` / `reject` / 追加の出口の key。送り終わると承認画面は run の画面へ戻る */
13
- decide: (port: string, value: unknown) => Promise<void>
14
- /** ホストの差し戻しダイアログを開く(理由と参考ファイルを入れて差し戻す) */
15
- openRejectDialog: () => Promise<void>
16
- /** 追加の出口に流す値を入れるダイアログを開く(`value` が初期値)。値の型が出口と合わないときに使う */
17
- openExitDialog: (key: string, value: unknown) => Promise<void>
18
- /** 承認画面を閉じて run の画面へ戻る(右上の × と同じ) */
19
- close: () => Promise<void>
20
- }
21
-
22
- const ApprovalActionsContext = createContext<ApprovalActions | null>(null)
23
-
24
- export const ApprovalActionsProvider = ApprovalActionsContext.Provider
25
-
26
- /** 承認画面の操作を頼む口(承認画面の中でだけ使える) */
27
- export const useApprovalActions = (): ApprovalActions => {
28
- const actions = useContext(ApprovalActionsContext)
29
- if (!actions) throw new Error("承認画面の中で使ってください")
30
- return actions
31
- }
package/views/index.ts DELETED
@@ -1,16 +0,0 @@
1
- // ビューの部品キット(`@mawaru/sdk/views`)。種類(承認・…)に依らない土台:部品・ホストに頼む口。
2
- // mawaru が顧客 repo のビューをまとめるとき、mawaru の今の版のこのキットを同梱する。
3
- // **公開 API**:部品の props とホストに頼む口は後方互換でしか変えない
4
- // (docs/tasks/wip/承認ビューの顧客repo配置.md の「互換の管理」)
5
- export { useViewBridge, type ViewBridge } from "./_bridge.js"
6
- export { documentCardStyle } from "./_parts/DocumentCard.js"
7
- export { FilePreview } from "./_parts/FilePreview.js"
8
- export { type FileRef, isFileRef } from "./_parts/fileRef.js"
9
- export { isUrl, Linkify, linkify } from "./_parts/Linkify.js"
10
- export { isLongText, Markdown, useAutoGrow } from "./_parts/Markdown.js"
11
- export {
12
- asFormSchema,
13
- type JsonSchema as FormSchema,
14
- SchemaForm,
15
- } from "./_parts/SchemaForm.js"
16
- export { NARROW_WIDTH, useNarrow } from "./_parts/useNarrow.js"