@shivaedev/work-board 0.17.0 → 0.17.1
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/CHANGELOG.md +14 -0
- package/README.md +4 -4
- package/assets/react.css +1 -1
- package/assets/react.js +34 -33
- package/dist/browser/responses/cardContext.d.ts +8 -1
- package/dist/browser/responses/cardContext.d.ts.map +1 -1
- package/dist/browser/responses/cardContext.js +14 -6
- package/dist/browser/responses/cardContext.js.map +1 -1
- package/dist/browser/views/schema.d.ts +11 -0
- package/dist/browser/views/schema.d.ts.map +1 -1
- package/dist/browser/views/schema.js +1 -0
- package/dist/browser/views/schema.js.map +1 -1
- package/dist/client/formStatus.d.ts +1 -1
- package/dist/client/formStatus.d.ts.map +1 -1
- package/dist/client/formStatus.js +2 -2
- package/dist/client/formStatus.js.map +1 -1
- package/dist/client/react/AnswerContext.d.ts.map +1 -1
- package/dist/client/react/AnswerContext.js +5 -2
- package/dist/client/react/AnswerContext.js.map +1 -1
- package/dist/client/react/AnswerForm.d.ts.map +1 -1
- package/dist/client/react/AnswerForm.js +6 -2
- package/dist/client/react/AnswerForm.js.map +1 -1
- package/dist/client/react/AnswerMarkdown.d.ts +6 -0
- package/dist/client/react/AnswerMarkdown.d.ts.map +1 -0
- package/dist/client/react/AnswerMarkdown.js +7 -0
- package/dist/client/react/AnswerMarkdown.js.map +1 -0
- package/dist/client/react/AnswerMore.d.ts.map +1 -1
- package/dist/client/react/AnswerMore.js +2 -1
- package/dist/client/react/AnswerMore.js.map +1 -1
- package/dist/client/react/AnswerPanel.d.ts.map +1 -1
- package/dist/client/react/AnswerPanel.js +3 -2
- package/dist/client/react/AnswerPanel.js.map +1 -1
- package/dist/client/react/AnswerPrompts.d.ts.map +1 -1
- package/dist/client/react/AnswerPrompts.js +16 -10
- package/dist/client/react/AnswerPrompts.js.map +1 -1
- package/dist/client/react/BoardShell.js +1 -1
- package/dist/client/react/BoardShell.js.map +1 -1
- package/dist/client/react/DocumentMain.d.ts.map +1 -1
- package/dist/client/react/DocumentMain.js +1 -1
- package/dist/client/react/DocumentMain.js.map +1 -1
- package/dist/client/react/GoalPage.js +1 -1
- package/dist/client/react/GoalPage.js.map +1 -1
- package/dist/client/react/GoalProgressHeader.js +1 -1
- package/dist/client/react/GoalProgressHeader.js.map +1 -1
- package/dist/client/react/LibraryMain.d.ts.map +1 -1
- package/dist/client/react/LibraryMain.js +1 -1
- package/dist/client/react/LibraryMain.js.map +1 -1
- package/dist/client/react/LibraryPage.js +1 -1
- package/dist/client/react/LibraryPage.js.map +1 -1
- package/dist/client/react/ProjectionMain.d.ts.map +1 -1
- package/dist/client/react/ProjectionMain.js +1 -1
- package/dist/client/react/ProjectionMain.js.map +1 -1
- package/dist/client/react/PromptOption.d.ts.map +1 -1
- package/dist/client/react/PromptOption.js +7 -5
- package/dist/client/react/PromptOption.js.map +1 -1
- package/dist/client/react/RemainingMain.d.ts.map +1 -1
- package/dist/client/react/RemainingMain.js +1 -1
- package/dist/client/react/RemainingMain.js.map +1 -1
- package/dist/client/react/ResponseHistory.d.ts.map +1 -1
- package/dist/client/react/ResponseHistory.js +11 -5
- package/dist/client/react/ResponseHistory.js.map +1 -1
- package/dist/client/react/SystemMain.d.ts.map +1 -1
- package/dist/client/react/SystemMain.js +1 -1
- package/dist/client/react/SystemMain.js.map +1 -1
- package/dist/client/react/TodayNeeds.d.ts +5 -0
- package/dist/client/react/TodayNeeds.d.ts.map +1 -1
- package/dist/client/react/TodayNeeds.js +6 -3
- package/dist/client/react/TodayNeeds.js.map +1 -1
- package/dist/client/react/TodayOptionButton.d.ts +15 -0
- package/dist/client/react/TodayOptionButton.d.ts.map +1 -0
- package/dist/client/react/TodayOptionButton.js +10 -0
- package/dist/client/react/TodayOptionButton.js.map +1 -0
- package/dist/client/react/TodayOptions.d.ts.map +1 -1
- package/dist/client/react/TodayOptions.js +11 -9
- package/dist/client/react/TodayOptions.js.map +1 -1
- package/dist/client/react/TodayPage.d.ts.map +1 -1
- package/dist/client/react/TodayPage.js +7 -4
- package/dist/client/react/TodayPage.js.map +1 -1
- package/dist/client/react/activeRead.js +1 -1
- package/dist/client/react/activeRead.js.map +1 -1
- package/dist/client/react/loadBoardPage.d.ts.map +1 -1
- package/dist/client/react/loadBoardPage.js +1 -1
- package/dist/client/react/loadBoardPage.js.map +1 -1
- package/dist/client/react/loadProjection.d.ts.map +1 -1
- package/dist/client/react/loadProjection.js +1 -1
- package/dist/client/react/loadProjection.js.map +1 -1
- package/dist/client/react/loadRemaining.d.ts +201 -201
- package/dist/client/react/loadRemaining.d.ts.map +1 -1
- package/dist/client/react/loadRemaining.js +1 -1
- package/dist/client/react/loadRemaining.js.map +1 -1
- package/dist/client/react/pageQueries.js +1 -1
- package/dist/client/react/pageQueries.js.map +1 -1
- package/dist/client/react/resolvedDocumentFailure.d.ts.map +1 -0
- package/dist/client/react/resolvedDocumentFailure.js.map +1 -0
- package/dist/client/react/routeQuery.d.ts.map +1 -0
- package/dist/client/react/routeQuery.js.map +1 -0
- package/dist/client/react/useResponseForm.d.ts.map +1 -1
- package/dist/client/react/useResponseForm.js +2 -2
- package/dist/client/react/useResponseForm.js.map +1 -1
- package/dist/client/responses/summary.d.ts +1 -0
- package/dist/client/responses/summary.d.ts.map +1 -1
- package/dist/client/responses/summary.js +12 -1
- package/dist/client/responses/summary.js.map +1 -1
- package/dist/rpc/contract.d.ts +33 -0
- package/dist/rpc/contract.d.ts.map +1 -1
- package/dist/server/attention/inbox.d.ts +13 -2
- package/dist/server/attention/inbox.d.ts.map +1 -1
- package/dist/server/attention/inbox.js +44 -27
- package/dist/server/attention/inbox.js.map +1 -1
- package/dist/server/attention/managedRequestReceipt.d.ts +10 -0
- package/dist/server/attention/managedRequestReceipt.d.ts.map +1 -1
- package/dist/server/attention/managedRequestReceipt.js +29 -10
- package/dist/server/attention/managedRequestReceipt.js.map +1 -1
- package/dist/server/attention/projection.d.ts.map +1 -1
- package/dist/server/attention/projection.js +2 -1
- package/dist/server/attention/projection.js.map +1 -1
- package/dist/server/attention/requestInbox.d.ts +3 -3
- package/dist/server/attention/requestInbox.js +2 -2
- package/dist/server/attention/requestInbox.js.map +1 -1
- package/dist/server/attention/requests.d.ts +1 -0
- package/dist/server/attention/requests.d.ts.map +1 -1
- package/dist/server/attention/requests.js +7 -3
- package/dist/server/attention/requests.js.map +1 -1
- package/dist/server/mcp/client.d.ts +874 -863
- package/dist/server/mcp/client.d.ts.map +1 -1
- package/dist/server/mcp/queries.d.ts +33 -0
- package/dist/server/mcp/queries.d.ts.map +1 -1
- package/dist/server/packageInfo.d.ts +1 -1
- package/dist/server/packageInfo.js +1 -1
- package/dist/server/views/projectionQueries.d.ts +11 -0
- package/dist/server/views/projectionQueries.d.ts.map +1 -1
- package/docs/delivery/README.md +2 -2
- package/package.json +4 -4
- package/src/browser/responses/cardContext.ts +15 -6
- package/src/browser/views/schema.ts +1 -0
- package/src/client/formStatus.ts +2 -2
- package/src/client/react/AnswerContext.tsx +9 -4
- package/src/client/react/AnswerForm.tsx +25 -6
- package/src/client/react/AnswerMarkdown.tsx +15 -0
- package/src/client/react/AnswerMore.tsx +58 -46
- package/src/client/react/AnswerPanel.tsx +14 -8
- package/src/client/react/AnswerPrompts.tsx +33 -18
- package/src/client/react/BoardShell.tsx +1 -1
- package/src/client/react/DocumentMain.tsx +1 -1
- package/src/client/react/GoalPage.tsx +1 -1
- package/src/client/react/GoalProgressHeader.tsx +1 -1
- package/src/client/react/LibraryMain.tsx +1 -1
- package/src/client/react/LibraryPage.tsx +1 -1
- package/src/client/react/ProjectionMain.tsx +1 -1
- package/src/client/react/PromptOption.tsx +39 -24
- package/src/client/react/RemainingMain.tsx +1 -1
- package/src/client/react/ResponseHistory.tsx +53 -14
- package/src/client/react/SystemMain.tsx +1 -1
- package/src/client/react/TodayNeeds.tsx +21 -6
- package/src/client/react/TodayOptionButton.tsx +37 -0
- package/src/client/react/TodayOptions.tsx +36 -28
- package/src/client/react/TodayPage.tsx +18 -3
- package/src/client/react/activeRead.ts +1 -1
- package/src/client/react/entry.css +0 -6
- package/src/client/react/loadBoardPage.ts +1 -1
- package/src/client/react/loadProjection.ts +1 -1
- package/src/client/react/loadRemaining.ts +1 -1
- package/src/client/react/pageQueries.ts +1 -1
- package/src/client/react/useResponseForm.ts +4 -2
- package/src/client/responses/summary.ts +13 -1
- package/src/server/attention/inbox.ts +51 -27
- package/src/server/attention/managedRequestReceipt.ts +41 -10
- package/src/server/attention/projection.ts +5 -2
- package/src/server/attention/requestInbox.ts +2 -2
- package/src/server/attention/requests.ts +7 -2
- package/src/server/packageInfo.ts +1 -1
- package/dist/client/page/resolvedDocumentFailure.d.ts.map +0 -1
- package/dist/client/page/resolvedDocumentFailure.js.map +0 -1
- package/dist/client/page/routeQuery.d.ts.map +0 -1
- package/dist/client/page/routeQuery.js.map +0 -1
- /package/dist/client/{page → react}/resolvedDocumentFailure.d.ts +0 -0
- /package/dist/client/{page → react}/resolvedDocumentFailure.js +0 -0
- /package/dist/client/{page → react}/routeQuery.d.ts +0 -0
- /package/dist/client/{page → react}/routeQuery.js +0 -0
- /package/src/client/{page → react}/resolvedDocumentFailure.ts +0 -0
- /package/src/client/{page → react}/routeQuery.ts +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/server/mcp/client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAS,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAoB,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;;;;AAI3D,qBAAa,cAAe,SAAQ,mBAAkF;CAAG;AAEzH,iBAAS,UAAU
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/server/mcp/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -903,6 +903,17 @@ export declare const needsYou: (client: import("effect/rpc/RpcClient").RpcClient
|
|
|
903
903
|
readonly responseFrom: import("effect/Schema").optional<import("effect/Schema").$Array<import("effect/Schema").String>>;
|
|
904
904
|
readonly title: import("effect/Schema").String;
|
|
905
905
|
}>>;
|
|
906
|
+
readonly later: import("effect/Schema").$Array<import("effect/Schema").Struct<{
|
|
907
|
+
readonly earlierAsks: import("effect/Schema").optional<import("effect/Schema").Number>;
|
|
908
|
+
readonly file: import("effect/Schema").String;
|
|
909
|
+
readonly href: import("effect/Schema").String;
|
|
910
|
+
readonly id: import("effect/Schema").String;
|
|
911
|
+
readonly modified: import("effect/Schema").optional<import("effect/Schema").Number>;
|
|
912
|
+
readonly problem: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
913
|
+
readonly reason: import("effect/Schema").String;
|
|
914
|
+
readonly responseFrom: import("effect/Schema").optional<import("effect/Schema").$Array<import("effect/Schema").String>>;
|
|
915
|
+
readonly title: import("effect/Schema").String;
|
|
916
|
+
}>>;
|
|
906
917
|
readonly parked: import("effect/Schema").$Array<import("effect/Schema").Struct<{
|
|
907
918
|
readonly earlierAsks: import("effect/Schema").optional<import("effect/Schema").Number>;
|
|
908
919
|
readonly file: import("effect/Schema").String;
|
|
@@ -2715,6 +2726,17 @@ export declare const overview: (client: import("effect/rpc/RpcClient").RpcClient
|
|
|
2715
2726
|
readonly responseFrom: import("effect/Schema").optional<import("effect/Schema").$Array<import("effect/Schema").String>>;
|
|
2716
2727
|
readonly title: import("effect/Schema").String;
|
|
2717
2728
|
}>>;
|
|
2729
|
+
readonly later: import("effect/Schema").$Array<import("effect/Schema").Struct<{
|
|
2730
|
+
readonly earlierAsks: import("effect/Schema").optional<import("effect/Schema").Number>;
|
|
2731
|
+
readonly file: import("effect/Schema").String;
|
|
2732
|
+
readonly href: import("effect/Schema").String;
|
|
2733
|
+
readonly id: import("effect/Schema").String;
|
|
2734
|
+
readonly modified: import("effect/Schema").optional<import("effect/Schema").Number>;
|
|
2735
|
+
readonly problem: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
2736
|
+
readonly reason: import("effect/Schema").String;
|
|
2737
|
+
readonly responseFrom: import("effect/Schema").optional<import("effect/Schema").$Array<import("effect/Schema").String>>;
|
|
2738
|
+
readonly title: import("effect/Schema").String;
|
|
2739
|
+
}>>;
|
|
2718
2740
|
readonly parked: import("effect/Schema").$Array<import("effect/Schema").Struct<{
|
|
2719
2741
|
readonly earlierAsks: import("effect/Schema").optional<import("effect/Schema").Number>;
|
|
2720
2742
|
readonly file: import("effect/Schema").String;
|
|
@@ -4683,6 +4705,17 @@ export declare const item: (client: import("effect/rpc/RpcClient").RpcClient.Fla
|
|
|
4683
4705
|
readonly responseFrom: import("effect/Schema").optional<import("effect/Schema").$Array<import("effect/Schema").String>>;
|
|
4684
4706
|
readonly title: import("effect/Schema").String;
|
|
4685
4707
|
}>>;
|
|
4708
|
+
readonly later: import("effect/Schema").$Array<import("effect/Schema").Struct<{
|
|
4709
|
+
readonly earlierAsks: import("effect/Schema").optional<import("effect/Schema").Number>;
|
|
4710
|
+
readonly file: import("effect/Schema").String;
|
|
4711
|
+
readonly href: import("effect/Schema").String;
|
|
4712
|
+
readonly id: import("effect/Schema").String;
|
|
4713
|
+
readonly modified: import("effect/Schema").optional<import("effect/Schema").Number>;
|
|
4714
|
+
readonly problem: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
4715
|
+
readonly reason: import("effect/Schema").String;
|
|
4716
|
+
readonly responseFrom: import("effect/Schema").optional<import("effect/Schema").$Array<import("effect/Schema").String>>;
|
|
4717
|
+
readonly title: import("effect/Schema").String;
|
|
4718
|
+
}>>;
|
|
4686
4719
|
readonly parked: import("effect/Schema").$Array<import("effect/Schema").Struct<{
|
|
4687
4720
|
readonly earlierAsks: import("effect/Schema").optional<import("effect/Schema").Number>;
|
|
4688
4721
|
readonly file: import("effect/Schema").String;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../../src/server/mcp/queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,MAAM,QAAQ,CAAC;AAQvC,eAAO,MAAM,QAAQ
|
|
1
|
+
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../../src/server/mcp/queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,MAAM,QAAQ,CAAC;AAQvC,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kUAkBnB,CAAC;AAEH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAWV,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;QAAqB,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kUAG9C,CAAC;AAEH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kUAef,CAAC"}
|
|
@@ -226,6 +226,17 @@ export declare const projectionQueries: Effect.Effect<{
|
|
|
226
226
|
readonly responseFrom?: readonly string[] | undefined;
|
|
227
227
|
readonly title: string;
|
|
228
228
|
}[];
|
|
229
|
+
readonly later: readonly {
|
|
230
|
+
readonly earlierAsks?: number | undefined;
|
|
231
|
+
readonly file: string;
|
|
232
|
+
readonly href: string;
|
|
233
|
+
readonly id: string;
|
|
234
|
+
readonly modified?: number | undefined;
|
|
235
|
+
readonly problem?: string | undefined;
|
|
236
|
+
readonly reason: string;
|
|
237
|
+
readonly responseFrom?: readonly string[] | undefined;
|
|
238
|
+
readonly title: string;
|
|
239
|
+
}[];
|
|
229
240
|
readonly parked: readonly {
|
|
230
241
|
readonly earlierAsks?: number | undefined;
|
|
231
242
|
readonly file: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projectionQueries.d.ts","sourceRoot":"","sources":["../../../src/server/views/projectionQueries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAahC,eAAO,MAAM,iBAAiB;iBAKf,MAAM
|
|
1
|
+
{"version":3,"file":"projectionQueries.d.ts","sourceRoot":"","sources":["../../../src/server/views/projectionQueries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAahC,eAAO,MAAM,iBAAiB;iBAKf,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAEP,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAmClB,CAAC"}
|
package/docs/delivery/README.md
CHANGED
|
@@ -36,8 +36,8 @@ The roadmap records whether each decision is settled and what it means for a ste
|
|
|
36
36
|
| [Board parser](https://github.com/ShivaeDev/platform/blob/main/packages/work-board/src/server/render/board.ts), [Markdown renderer](https://github.com/ShivaeDev/platform/blob/main/packages/work-board/src/server/render/markdown.ts) | Source interpretation and semantic reading | Heading boards, GFM, references and readable fallback |
|
|
37
37
|
| [Page route](https://github.com/ShivaeDev/platform/blob/main/packages/work-board/src/server/http/page.ts), [router](https://github.com/ShivaeDev/platform/blob/main/packages/work-board/src/server/board.ts) | Locations, projections and HTTP composition | Loopback boundary, embedding and Effect scope/errors |
|
|
38
38
|
| [Listing](https://github.com/ShivaeDev/platform/blob/main/packages/work-board/src/server/files/list.ts), [watcher](https://github.com/ShivaeDev/platform/blob/main/packages/work-board/src/server/files/changes.ts) | File discovery and freshness | Root policy, rename/delete handling and recovery |
|
|
39
|
-
| [Native client](https://github.com/ShivaeDev/platform/blob/main/packages/work-board/src/client/client.ts), [
|
|
40
|
-
| [Assets](https://github.com/ShivaeDev/platform/blob/main/packages/work-board/src/server/http/assets.ts), [diagrams](https://github.com/ShivaeDev/platform/blob/main/packages/work-board/src/client/
|
|
39
|
+
| [Native client](https://github.com/ShivaeDev/platform/blob/main/packages/work-board/src/client/client.ts), [React navigation](https://github.com/ShivaeDev/platform/blob/main/packages/work-board/src/client/react/useBoardNavigation.ts) | Scoped reads and retained reading state | Shared Effect contracts/live primitives, clear failures and reconciliation |
|
|
40
|
+
| [Assets](https://github.com/ShivaeDev/platform/blob/main/packages/work-board/src/server/http/assets.ts), [diagrams](https://github.com/ShivaeDev/platform/blob/main/packages/work-board/src/client/document/Mermaid.ts) | Local visual reading | Bounded access and locally loaded renderers |
|
|
41
41
|
|
|
42
42
|
Keep CLI and embedding working together. Static mockup markup and fictional data are review aids, not the production data model. A new framework, persistent store or adapter must earn its cost through an agreed requirement.
|
|
43
43
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/work-board",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.1",
|
|
4
4
|
"description": "Serve a folder of markdown files as a live local page that updates in place when a file changes",
|
|
5
5
|
"homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/work-board#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -411,7 +411,7 @@
|
|
|
411
411
|
"dependencies": {
|
|
412
412
|
"@shivaedev/effect-contract": "0.5.1",
|
|
413
413
|
"@shivaedev/effect-service": "0.3.0",
|
|
414
|
-
"@shivaedev/platform": "0.
|
|
414
|
+
"@shivaedev/platform": "0.15.0",
|
|
415
415
|
"mdast-util-directive": "3.1.1",
|
|
416
416
|
"mermaid": "12.1.0",
|
|
417
417
|
"react": "19.3.0",
|
|
@@ -433,8 +433,8 @@
|
|
|
433
433
|
"@shivaedev/effect-form": "0.4.0",
|
|
434
434
|
"@shivaedev/effect-react": "0.4.1",
|
|
435
435
|
"@shivaedev/effect-test": "0.5.0",
|
|
436
|
-
"@shivaedev/quality": "0.
|
|
437
|
-
"@shivaedev/test-story": "0.
|
|
436
|
+
"@shivaedev/quality": "0.24.0",
|
|
437
|
+
"@shivaedev/test-story": "0.7.0",
|
|
438
438
|
"@tailwindcss/vite": "4.3.3",
|
|
439
439
|
"@tanstack/react-router": "1.170.42",
|
|
440
440
|
"@types/hast": "3.0.5",
|
|
@@ -10,15 +10,19 @@ export function cardContext(source: string) {
|
|
|
10
10
|
return { links, recommendation };
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export function
|
|
14
|
-
const heading =
|
|
15
|
-
if (heading) {
|
|
16
|
-
return heading;
|
|
13
|
+
export function optionText(id: string, source: string, reason: string) {
|
|
14
|
+
const heading = promptHeading(source);
|
|
15
|
+
if (heading.title) {
|
|
16
|
+
return { description: heading.rest, label: heading.title };
|
|
17
|
+
}
|
|
18
|
+
const lead = /^\*\*(?<label>[^*]+)\*\*\s*(?:[—–:-]\s*)?/u.exec(source.trim());
|
|
19
|
+
if (lead?.groups?.label) {
|
|
20
|
+
return { description: source.trim().slice(lead[0].length).trim(), label: lead.groups.label.trim() };
|
|
17
21
|
}
|
|
18
22
|
if (id === "retry" && /reviewed pr is ready to merge/iu.test(reason)) {
|
|
19
|
-
return "Request changes (retry)";
|
|
23
|
+
return { description: source.trim(), label: "Request changes (retry)" };
|
|
20
24
|
}
|
|
21
|
-
return id.charAt(0).toUpperCase() + id.slice(1).replaceAll("-", " ");
|
|
25
|
+
return { description: source.trim(), label: id.charAt(0).toUpperCase() + id.slice(1).replaceAll("-", " ") };
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
function section(source: string, title: string) {
|
|
@@ -48,3 +52,8 @@ function section(source: string, title: string) {
|
|
|
48
52
|
function nextFence(current: string | undefined, marker: string) {
|
|
49
53
|
return current?.startsWith(marker.charAt(0)) && marker.length >= current.length ? undefined : marker;
|
|
50
54
|
}
|
|
55
|
+
|
|
56
|
+
export function promptHeading(source: string) {
|
|
57
|
+
const heading = /^#{1,6}\s+(?<title>.+)$/mu.exec(source);
|
|
58
|
+
return { rest: heading ? source.replace(heading[0], "").trim() : source.trim(), title: heading?.groups?.title?.trim() };
|
|
59
|
+
}
|
|
@@ -40,6 +40,7 @@ export const InboxProjection = Schema.Struct({
|
|
|
40
40
|
complete: Schema.Boolean,
|
|
41
41
|
issues: Schema.Array(Schema.Struct({ file: Schema.String, line: Schema.Number, message: Schema.String })),
|
|
42
42
|
items: Schema.Array(InboxItem),
|
|
43
|
+
later: Schema.Array(InboxItem),
|
|
43
44
|
parked: Schema.Array(InboxItem),
|
|
44
45
|
resolved: Schema.Array(InboxItem),
|
|
45
46
|
sourceIssues: Schema.Boolean,
|
package/src/client/formStatus.ts
CHANGED
|
@@ -30,6 +30,6 @@ export function formStatus<A>(
|
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export function responseSaved(id: string, dirty: boolean) {
|
|
34
|
-
return `Saved: responses/${id}.md. This records
|
|
33
|
+
export function responseSaved(id: string, dirty: boolean, choice = "") {
|
|
34
|
+
return `Saved: your answer${choice ? ` “${choice}”` : ""} is recorded. The agent reads it from responses/${id}.md the next time it checks. This records your answer, not acceptance of the work.${dirty ? " Your current draft remains unsaved." : ""}`;
|
|
35
35
|
}
|
|
@@ -1,25 +1,30 @@
|
|
|
1
|
+
import { ExternalLink } from "lucide-react";
|
|
1
2
|
import { cardContext } from "#browser/responses/cardContext.ts";
|
|
2
3
|
import type { QuestionPreview } from "#browser/responses/schema.ts";
|
|
3
|
-
import {
|
|
4
|
+
import { buttonVariants } from "#client/react/components/ui/buttonVariants.ts";
|
|
5
|
+
import { cn } from "#client/react/lib/cn.ts";
|
|
6
|
+
import { AnswerMarkdown } from "./AnswerMarkdown.tsx";
|
|
4
7
|
|
|
5
8
|
export function AnswerContext({ preview }: { readonly preview: QuestionPreview }) {
|
|
6
9
|
const context = cardContext(preview.context);
|
|
7
10
|
return (
|
|
8
11
|
<>
|
|
9
12
|
{Boolean(context.recommendation) && (
|
|
10
|
-
<div className="
|
|
11
|
-
<
|
|
13
|
+
<div className="rounded-lg bg-muted/60 px-4 py-3 text-sm">
|
|
14
|
+
<p className="mb-1 font-medium text-muted-foreground text-xs uppercase tracking-wide">Recommendation</p>
|
|
15
|
+
<AnswerMarkdown className="answer-recommendation" file={preview.source} source={context.recommendation} />
|
|
12
16
|
</div>
|
|
13
17
|
)}
|
|
14
18
|
{context.links.length > 0 && (
|
|
15
19
|
<div className="answer-links flex flex-wrap gap-2">
|
|
16
20
|
{context.links.map((link) => (
|
|
17
21
|
<a
|
|
18
|
-
className={
|
|
22
|
+
className={cn(buttonVariants({ size: "sm", variant: link.primary ? "default" : "outline" }), "answer-link")}
|
|
19
23
|
href={link.url}
|
|
20
24
|
key={link.url}
|
|
21
25
|
>
|
|
22
26
|
{link.label}
|
|
27
|
+
<ExternalLink aria-hidden="true" />
|
|
23
28
|
</a>
|
|
24
29
|
))}
|
|
25
30
|
</div>
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { CheckCircle2 } from "lucide-react";
|
|
1
2
|
import type { Document, DocumentRequest } from "#browser/document/schema.ts";
|
|
2
3
|
import type { QuestionPreview } from "#browser/responses/schema.ts";
|
|
4
|
+
import { Button } from "#client/react/components/ui/Button.tsx";
|
|
5
|
+
import { cn } from "#client/react/lib/cn.ts";
|
|
3
6
|
import { AnswerMore } from "./AnswerMore.tsx";
|
|
4
7
|
import { AnswerPrompts } from "./AnswerPrompts.tsx";
|
|
5
8
|
import { FormField } from "./FormField.tsx";
|
|
@@ -7,6 +10,8 @@ import { shellIds } from "./shellIds.ts";
|
|
|
7
10
|
import { useFormFocus } from "./useFormFocus.ts";
|
|
8
11
|
import { useResponseForm } from "./useResponseForm.ts";
|
|
9
12
|
|
|
13
|
+
const READ_ONLY = "This Board is read-only. Start it with --responses to record answers.";
|
|
14
|
+
|
|
10
15
|
interface AnswerProps {
|
|
11
16
|
readonly document: Document;
|
|
12
17
|
readonly preview: QuestionPreview;
|
|
@@ -38,6 +43,7 @@ function AnswerSession({ document: data, request, preview }: AnswerProps) {
|
|
|
38
43
|
return (
|
|
39
44
|
<form
|
|
40
45
|
{...focus}
|
|
46
|
+
className="space-y-4"
|
|
41
47
|
data-item={preview.item}
|
|
42
48
|
data-question={preview.id}
|
|
43
49
|
data-request={preview.request}
|
|
@@ -76,13 +82,26 @@ function AnswerSession({ document: data, request, preview }: AnswerProps) {
|
|
|
76
82
|
showErrors={state.attempted}
|
|
77
83
|
/>
|
|
78
84
|
{prompts.length === 0 && body}
|
|
79
|
-
<
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
<div className="flex flex-wrap items-center gap-3">
|
|
86
|
+
<Button disabled={!data.writable || state.created.saving} id={id(shellIds.responseSubmit)} type="submit">
|
|
87
|
+
Record answer
|
|
88
|
+
</Button>
|
|
89
|
+
</div>
|
|
90
|
+
<p
|
|
91
|
+
className={cn(
|
|
92
|
+
"flex items-start gap-2 text-sm empty:hidden",
|
|
93
|
+
!data.writable && "text-muted-foreground",
|
|
94
|
+
state.outcome === "saved" && "rounded-md border border-done/40 bg-done/10 px-3 py-2",
|
|
95
|
+
(state.outcome === "rejected" || state.outcome === "uncertain") && "rounded-md border border-destructive/40 px-3 py-2 text-destructive",
|
|
96
|
+
)}
|
|
97
|
+
data-outcome={state.outcome}
|
|
98
|
+
id={id(shellIds.responseStatus)}
|
|
99
|
+
role="status"
|
|
100
|
+
>
|
|
101
|
+
{state.outcome === "saved" && <CheckCircle2 aria-hidden="true" className="mt-0.5 size-4 shrink-0 text-done" />}
|
|
102
|
+
{data.writable ? writableStatus : `${state.status} ${READ_ONLY}`.trim()}
|
|
85
103
|
</p>
|
|
104
|
+
<AnswerMore body={prompts.length > 0 ? body : undefined} id={id} request={request} state={state} />
|
|
86
105
|
</form>
|
|
87
106
|
);
|
|
88
107
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { cn } from "#client/react/lib/cn.ts";
|
|
2
|
+
import { ResponseMarkdown } from "./ResponseMarkdown.tsx";
|
|
3
|
+
|
|
4
|
+
export function AnswerMarkdown({ className, file, source }: { readonly className?: string; readonly file: string; readonly source: string }) {
|
|
5
|
+
return (
|
|
6
|
+
<div
|
|
7
|
+
className={cn(
|
|
8
|
+
"[&_a]:underline [&_a]:underline-offset-4 [&_code]:font-mono [&_code]:text-[0.9em] [&_li]:my-1 [&_ol]:list-decimal [&_ol]:pl-5 [&_p+p]:mt-2 [&_ul]:list-disc [&_ul]:pl-5",
|
|
9
|
+
className,
|
|
10
|
+
)}
|
|
11
|
+
>
|
|
12
|
+
<ResponseMarkdown file={file} source={source} />
|
|
13
|
+
</div>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import type { DocumentRequest } from "#browser/document/schema.ts";
|
|
3
|
+
import { Button } from "#client/react/components/ui/Button.tsx";
|
|
3
4
|
import { FormField } from "./FormField.tsx";
|
|
4
5
|
import { shellIds } from "./shellIds.ts";
|
|
5
6
|
import type { useResponseForm } from "./useResponseForm.ts";
|
|
@@ -16,52 +17,63 @@ export function AnswerMore({
|
|
|
16
17
|
readonly state: ReturnType<typeof useResponseForm>;
|
|
17
18
|
}) {
|
|
18
19
|
return (
|
|
19
|
-
<details data-key="response-details">
|
|
20
|
-
<summary>More</summary>
|
|
21
|
-
<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
{record.id}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
{state.recovery}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
20
|
+
<details className="group rounded-lg border px-4 py-2 text-sm [&[open]]:pb-4" data-key="response-details">
|
|
21
|
+
<summary className="cursor-pointer select-none py-1 text-muted-foreground hover:text-foreground">More options</summary>
|
|
22
|
+
<div className="mt-3 grid gap-4">
|
|
23
|
+
<FormField
|
|
24
|
+
autoComplete="nickname"
|
|
25
|
+
form={state.form}
|
|
26
|
+
label="Local author label"
|
|
27
|
+
maxLength={200}
|
|
28
|
+
name="author"
|
|
29
|
+
required
|
|
30
|
+
showErrors={state.attempted}
|
|
31
|
+
/>
|
|
32
|
+
<FormField form={state.form} label="Response kind" name="type">
|
|
33
|
+
<option value="answer">Answer (including no)</option>
|
|
34
|
+
<option value="clarify">Ask back / clarify</option>
|
|
35
|
+
<option value="not_now">Not now</option>
|
|
36
|
+
</FormField>
|
|
37
|
+
{body}
|
|
38
|
+
<FormField form={state.form} label="Supersedes an earlier response (optional)" name="supersedes">
|
|
39
|
+
<option value="">Adds feedback; does not supersede</option>
|
|
40
|
+
{request.responses?.map((record) => (
|
|
41
|
+
<option key={record.id} value={record.id}>
|
|
42
|
+
{record.id} · {record.response.author} · {record.response.reviewedRevision.slice(0, 12)}
|
|
43
|
+
</option>
|
|
44
|
+
))}
|
|
45
|
+
</FormField>
|
|
46
|
+
<pre className="whitespace-pre-wrap rounded-md bg-muted p-3 text-xs" hidden={!state.recovery} id={id(shellIds.responseDraftRecovery)}>
|
|
47
|
+
{state.recovery}
|
|
48
|
+
</pre>
|
|
49
|
+
<p className="text-muted-foreground text-xs">
|
|
50
|
+
Drafts stay in this browser for seven days after the last edit, with a 256 KiB limit per draft. Saved responses are Markdown files in
|
|
51
|
+
responses/.
|
|
52
|
+
</p>
|
|
53
|
+
<div className="flex flex-wrap gap-2">
|
|
54
|
+
<Button
|
|
55
|
+
disabled={typeof window === "undefined" || state.created.saving}
|
|
56
|
+
id={id(shellIds.responsePreview)}
|
|
57
|
+
onClick={state.showPreview}
|
|
58
|
+
size="sm"
|
|
59
|
+
variant="outline"
|
|
60
|
+
>
|
|
61
|
+
Preview Markdown
|
|
62
|
+
</Button>
|
|
63
|
+
<Button
|
|
64
|
+
disabled={typeof window === "undefined" || state.created.saving}
|
|
65
|
+
id={id(shellIds.responseClear)}
|
|
66
|
+
onClick={state.clear}
|
|
67
|
+
size="sm"
|
|
68
|
+
variant="ghost"
|
|
69
|
+
>
|
|
70
|
+
Clear draft
|
|
71
|
+
</Button>
|
|
72
|
+
</div>
|
|
73
|
+
<pre className="whitespace-pre-wrap rounded-md bg-muted p-3 text-xs" hidden={!state.preview} id={id(shellIds.responsePreviewContent)}>
|
|
74
|
+
{state.preview}
|
|
75
|
+
</pre>
|
|
76
|
+
</div>
|
|
65
77
|
</details>
|
|
66
78
|
);
|
|
67
79
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { MessageCircleQuestion } from "lucide-react";
|
|
1
2
|
import type { Document, DocumentRequest } from "#browser/document/schema.ts";
|
|
2
3
|
import { reasonMarkdown } from "#browser/responses/reasonMarkdown.ts";
|
|
3
4
|
import { AnswerContext } from "./AnswerContext.tsx";
|
|
4
5
|
import { AnswerForm } from "./AnswerForm.tsx";
|
|
6
|
+
import { AnswerMarkdown } from "./AnswerMarkdown.tsx";
|
|
5
7
|
import { ResponseHistory } from "./ResponseHistory.tsx";
|
|
6
|
-
import { ResponseMarkdown } from "./ResponseMarkdown.tsx";
|
|
7
8
|
|
|
8
9
|
export function AnswerPanel({ document: data }: { readonly document: Document }) {
|
|
9
10
|
const requests = data.requests.filter(
|
|
@@ -30,23 +31,28 @@ function AnswerCard({ document: data, request }: { readonly document: Document;
|
|
|
30
31
|
return (
|
|
31
32
|
<section
|
|
32
33
|
aria-labelledby={`answer-title-${request.id}`}
|
|
33
|
-
className="response-panel
|
|
34
|
+
className="response-panel max-w-[72ch] space-y-5 rounded-xl border bg-card p-5 text-card-foreground shadow-sm"
|
|
34
35
|
id={`answer-card-${request.id}`}
|
|
35
36
|
tabIndex={-1}
|
|
36
37
|
>
|
|
37
|
-
<h2 id={`answer-title-${request.id}`}>
|
|
38
|
+
<h2 className="flex items-center gap-2 font-medium text-muted-foreground text-sm" id={`answer-title-${request.id}`}>
|
|
39
|
+
{request.open ? <MessageCircleQuestion aria-hidden="true" className="size-4 text-needs-you" /> : null}
|
|
40
|
+
{cardTitle(request, closed)}
|
|
41
|
+
</h2>
|
|
38
42
|
{!(request.open || unavailable) && (
|
|
39
|
-
<p role="status">
|
|
43
|
+
<p className="text-muted-foreground text-sm" role="status">
|
|
40
44
|
{closed ? "This question is closed. Recorded answers remain below." : "Answer unavailable. Check the source diagnostics."}
|
|
41
45
|
</p>
|
|
42
46
|
)}
|
|
43
|
-
{Boolean(unavailable) &&
|
|
47
|
+
{Boolean(unavailable) && (
|
|
48
|
+
<p className="rounded-md border border-destructive/40 px-3 py-2 text-sm" role="status">
|
|
49
|
+
{unavailable}
|
|
50
|
+
</p>
|
|
51
|
+
)}
|
|
44
52
|
{request.open && preview !== undefined && (
|
|
45
53
|
<>
|
|
54
|
+
<AnswerMarkdown className="answer-reason font-medium text-base" file={source.file} source={reasonMarkdown(preview.reason)} />
|
|
46
55
|
<AnswerContext preview={preview} />
|
|
47
|
-
<div className="answer-reason">
|
|
48
|
-
<ResponseMarkdown file={source.file} source={reasonMarkdown(preview.reason)} />
|
|
49
|
-
</div>
|
|
50
56
|
</>
|
|
51
57
|
)}
|
|
52
58
|
{request.open && preview && !unavailable && <AnswerForm document={source} preview={preview} request={request} />}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { useAtomValue } from "@effect/atom-react";
|
|
2
2
|
import { useId, useLayoutEffect, useRef } from "react";
|
|
3
3
|
import type { Document } from "#browser/document/schema.ts";
|
|
4
|
+
import { promptHeading } from "#browser/responses/cardContext.ts";
|
|
4
5
|
import type { Prompt } from "#browser/responses/Prompt.ts";
|
|
5
6
|
import type { PromptAnswer } from "#browser/responses/schema.ts";
|
|
7
|
+
import { AnswerMarkdown } from "./AnswerMarkdown.tsx";
|
|
6
8
|
import { PromptOption } from "./PromptOption.tsx";
|
|
7
|
-
import { ResponseMarkdown } from "./ResponseMarkdown.tsx";
|
|
8
9
|
import type { useResponseForm } from "./useResponseForm.ts";
|
|
9
10
|
|
|
10
11
|
type Model = ReturnType<typeof useResponseForm>["form"];
|
|
@@ -36,12 +37,9 @@ function PromptField({
|
|
|
36
37
|
useLayoutEffect(() => ref.current?.setCustomValidity(error ?? ""), [error]);
|
|
37
38
|
const choices = document.metadata.options;
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
} else if (prompt.mode !== "text") {
|
|
43
|
-
guidance = `${prompt.mode === "one" ? "Choose one option" : "Choose any combination"}, or answer in your own words.`;
|
|
44
|
-
}
|
|
40
|
+
const guidance = promptGuidance(prompt.mode, choices !== undefined);
|
|
41
|
+
const heading = promptHeading(prompt.source);
|
|
42
|
+
const title = heading.title ?? `Question ${index + 1}`;
|
|
45
43
|
function change(next: PromptAnswer) {
|
|
46
44
|
onEdit(index, next);
|
|
47
45
|
}
|
|
@@ -57,14 +55,14 @@ function PromptField({
|
|
|
57
55
|
}
|
|
58
56
|
let message = error;
|
|
59
57
|
if (error && answer.selected.length === 0 && !answer.text.trim()) {
|
|
60
|
-
message = `Unanswered:
|
|
58
|
+
message = `Unanswered: “${title}”. Choose an option or answer in your own words.`;
|
|
61
59
|
}
|
|
62
60
|
return (
|
|
63
|
-
<fieldset data-mode={prompt.mode} data-prompt={prompt.id} data-source={prompt.source}>
|
|
64
|
-
<legend>{choices ? "Your answer"
|
|
65
|
-
{choices === undefined && <
|
|
66
|
-
<p>{guidance}
|
|
67
|
-
<div className={choices ? "question-choices" :
|
|
61
|
+
<fieldset className="m-0 min-w-0 space-y-3 border-0 p-0" data-mode={prompt.mode} data-prompt={prompt.id} data-source={prompt.source}>
|
|
62
|
+
<legend className="mb-1 p-0 font-semibold text-base">{choices === undefined ? title : "Your answer"}</legend>
|
|
63
|
+
{choices === undefined && heading.rest ? <AnswerMarkdown className="text-sm" file={document.file} source={heading.rest} /> : null}
|
|
64
|
+
<p className="text-muted-foreground text-sm">{guidance}</p>
|
|
65
|
+
<div className={`grid gap-2 ${choices ? "question-choices" : ""}`}>
|
|
68
66
|
{prompt.options.map((option, choice) => (
|
|
69
67
|
<PromptOption
|
|
70
68
|
checked={answer.selected.includes(option.id)}
|
|
@@ -78,26 +76,43 @@ function PromptField({
|
|
|
78
76
|
))}
|
|
79
77
|
</div>
|
|
80
78
|
{prompt.mode !== "text" && (
|
|
81
|
-
<button
|
|
79
|
+
<button
|
|
80
|
+
className="text-muted-foreground text-xs underline-offset-4 hover:underline disabled:opacity-50"
|
|
81
|
+
data-clear-choices
|
|
82
|
+
disabled={answer.selected.length === 0}
|
|
83
|
+
onClick={() => change({ ...answer, selected: [] })}
|
|
84
|
+
type="button"
|
|
85
|
+
>
|
|
82
86
|
Clear selections
|
|
83
87
|
</button>
|
|
84
88
|
)}
|
|
85
|
-
<label>
|
|
86
|
-
{
|
|
89
|
+
<label className="grid gap-2 text-sm">
|
|
90
|
+
<span>{prompt.mode === "text" ? "Your answer" : "Add a note or answer in your own words (optional)"}</span>
|
|
87
91
|
<textarea
|
|
88
92
|
aria-describedby={`${errorId}-error`}
|
|
89
93
|
aria-invalid={Boolean(error)}
|
|
94
|
+
className="w-full rounded-md border bg-background px-3 py-2 text-sm aria-invalid:border-destructive"
|
|
90
95
|
data-answer-text
|
|
91
96
|
maxLength={8192}
|
|
92
97
|
onInput={(event) => change({ ...answer, text: event.currentTarget.value })}
|
|
93
98
|
ref={ref}
|
|
94
|
-
rows={choices ? 4 :
|
|
99
|
+
rows={choices || prompt.mode === "text" ? 4 : 2}
|
|
95
100
|
value={answer.text}
|
|
96
101
|
/>
|
|
97
|
-
<span className="response-field-error" hidden={!error} id={`${errorId}-error`}>
|
|
102
|
+
<span className="response-field-error text-destructive text-xs" hidden={!error} id={`${errorId}-error`}>
|
|
98
103
|
{message}
|
|
99
104
|
</span>
|
|
100
105
|
</label>
|
|
101
106
|
</fieldset>
|
|
102
107
|
);
|
|
103
108
|
}
|
|
109
|
+
|
|
110
|
+
function promptGuidance(mode: Prompt["mode"], authored: boolean) {
|
|
111
|
+
if (authored) {
|
|
112
|
+
return "Choose an option or write another answer. Nothing is selected for you.";
|
|
113
|
+
}
|
|
114
|
+
if (mode === "text") {
|
|
115
|
+
return "Answer in your own words.";
|
|
116
|
+
}
|
|
117
|
+
return `${mode === "one" ? "Choose one option" : "Choose any combination"}, or answer in your own words. Nothing is selected for you.`;
|
|
118
|
+
}
|