weaver-work-cli 0.1.23 → 0.1.25
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/README.md +33 -3
- package/dist/core/output.js +53 -1
- package/dist/internal/e10/auth/commands.js +210 -17
- package/dist/internal/e10/auth/crypto.js +52 -12
- package/dist/internal/e10/auth/xiaoe.js +117 -35
- package/dist/internal/e10/context.js +3 -3
- package/dist/internal/e10/request-runtime.js +46 -4
- package/dist/shortcuts/caizhilian/file-upload/metadata.js +124 -0
- package/dist/shortcuts/caizhilian/file-upload/multipart.js +47 -0
- package/dist/shortcuts/caizhilian/file-upload/protocol.js +116 -0
- package/dist/shortcuts/caizhilian/file-upload/receipt.js +37 -0
- package/dist/shortcuts/caizhilian/host.js +13 -5
- package/dist/shortcuts/caizhilian/operations/handlers/file-upload.js +72 -179
- package/dist/shortcuts/caizhilian/operations/handlers/fileops.js +67 -1
- package/dist/shortcuts/caizhilian/operations/handlers/folder.js +701 -4
- package/dist/shortcuts/caizhilian/operations/handlers/setting-attach.js +198 -0
- package/dist/shortcuts/caizhilian/operations/registry.js +5 -1
- package/dist/shortcuts/caizhilian/operations/shared.js +32 -0
- package/dist/shortcuts/caizhilian/operations/specs.js +67 -0
- package/dist/shortcuts/workflow/continuation.js +14 -9
- package/dist/shortcuts/workflow/endpoints.js +11 -1
- package/dist/shortcuts/workflow/index.js +55 -1
- package/dist/shortcuts/workflow/operations/flow-status.js +63 -0
- package/dist/shortcuts/workflow/operations/form.js +1822 -547
- package/dist/shortcuts/workflow/operations/read.js +414 -13
- package/dist/shortcuts/workflow/operations/shared.js +28 -0
- package/dist/shortcuts/workflow/operations/write.js +5 -5
- package/dist/shortcuts/workflow/operations.js +8 -6
- package/dist/shortcuts/workflow/stdout-compact.js +33 -0
- package/docs/caizhilian.md +12 -5
- package/docs/e10-auth.md +25 -3
- package/node_modules/@napi-rs/keyring/LICENSE +21 -0
- package/node_modules/@napi-rs/keyring/README.md +19 -0
- package/node_modules/@napi-rs/keyring/index.d.ts +166 -0
- package/node_modules/@napi-rs/keyring/index.js +514 -0
- package/node_modules/@napi-rs/keyring/keytar.d.ts +53 -0
- package/node_modules/@napi-rs/keyring/keytar.js +26 -0
- package/node_modules/@napi-rs/keyring/package.json +125 -0
- package/node_modules/@napi-rs/keyring-darwin-arm64/README.md +3 -0
- package/node_modules/@napi-rs/keyring-darwin-arm64/keyring.darwin-arm64.node +0 -0
- package/node_modules/@napi-rs/keyring-darwin-arm64/package.json +32 -0
- package/node_modules/commander/LICENSE +22 -0
- package/node_modules/commander/Readme.md +1149 -0
- package/node_modules/commander/esm.mjs +16 -0
- package/node_modules/commander/index.js +24 -0
- package/node_modules/commander/lib/argument.js +149 -0
- package/node_modules/commander/lib/command.js +2662 -0
- package/node_modules/commander/lib/error.js +39 -0
- package/node_modules/commander/lib/help.js +709 -0
- package/node_modules/commander/lib/option.js +367 -0
- package/node_modules/commander/lib/suggestSimilar.js +101 -0
- package/node_modules/commander/package-support.json +16 -0
- package/node_modules/commander/package.json +82 -0
- package/node_modules/commander/typings/esm.d.mts +3 -0
- package/node_modules/commander/typings/index.d.ts +1045 -0
- package/package.json +5 -1
- package/skills/weaver-e10-builder/SKILL.md +281 -0
- package/skills/weaver-e10-builder/_catalog.md +94 -0
- package/skills/weaver-e10-builder/actionflows/CONTEXT.md +71 -0
- package/skills/weaver-e10-builder/actionflows/SKILL.md +176 -0
- package/skills/weaver-e10-builder/actionflows/docs/adr/0001-generated-actionflow-cleanup-identity.md +5 -0
- package/skills/weaver-e10-builder/actionflows/docs/adr/0002-preserve-existing-actionflow-on-update.md +36 -0
- package/skills/weaver-e10-builder/actionflows/references/components/calendar/MeetingCreate.md +19 -0
- package/skills/weaver-e10-builder/actionflows/references/components/calendar/ScheduleCreate.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/database/DMLExecute.md +38 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/AttachmentCopy.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/AttachmentMove.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/DocumentCopy.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/DocumentDelete.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/DocumentEdit.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/DocumentMove.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/DocumentPermissionChange.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/DocumentRenewal.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/DocumentRevert.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/DocumentSave.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/DocumentSubscription.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/DocumentSubscriptionApprove.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/DocumentSubscriptionSendBack.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/DocumentSubscriptionWithdraw.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/FileFolderSave.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/GetAttachmentInfo.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/GetDocumentInfo.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/ModifyDocumentStatus.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/ReplaceAttachment.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/document/UpdatePrintNum.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/ebuilder/ActionEbAdd.md +100 -0
- package/skills/weaver-e10-builder/actionflows/references/components/ebuilder/ActionEbDelete.md +23 -0
- package/skills/weaver-e10-builder/actionflows/references/components/ebuilder/ActionEbRecover.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/ebuilder/ActionEbSaveVersion.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/ebuilder/ActionEbUpdate.md +67 -0
- package/skills/weaver-e10-builder/actionflows/references/components/ebuilder/DateTrigger.md +32 -0
- package/skills/weaver-e10-builder/actionflows/references/components/ebuilder/EbGetDataById.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/ebuilder/EnquiryForm.md +107 -0
- package/skills/weaver-e10-builder/actionflows/references/components/ebuilder/EventButton.md +33 -0
- package/skills/weaver-e10-builder/actionflows/references/components/ebuilder/EventFormData.md +19 -0
- package/skills/weaver-e10-builder/actionflows/references/components/ebuilder/TimeBatchTrigger.md +19 -0
- package/skills/weaver-e10-builder/actionflows/references/components/http/Http.md +77 -0
- package/skills/weaver-e10-builder/actionflows/references/components/logic/Condition.md +23 -0
- package/skills/weaver-e10-builder/actionflows/references/components/logic/LogicFlowSet.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/logic/MultipleExecution.md +38 -0
- package/skills/weaver-e10-builder/actionflows/references/components/logic/Output.md +37 -0
- package/skills/weaver-e10-builder/actionflows/references/components/message/InnerMQSend.md +50 -0
- package/skills/weaver-e10-builder/actionflows/references/components/message/SendMessage.md +30 -0
- package/skills/weaver-e10-builder/actionflows/references/components/personnel/AlterPersonStatus.md +30 -0
- package/skills/weaver-e10-builder/actionflows/references/components/personnel/HrmEmployeeUpdate.md +34 -0
- package/skills/weaver-e10-builder/actionflows/references/components/personnel/PersonnelAlterType.md +38 -0
- package/skills/weaver-e10-builder/actionflows/references/components/personnel/PersonnelOnboarding.md +36 -0
- package/skills/weaver-e10-builder/actionflows/references/components/serverless/ServerlessAction.md +42 -0
- package/skills/weaver-e10-builder/actionflows/references/components/trigger/CustomTrigger.md +82 -0
- package/skills/weaver-e10-builder/actionflows/references/components/trigger/InnerMQListener.md +41 -0
- package/skills/weaver-e10-builder/actionflows/references/components/trigger/SimpleScheduler.md +19 -0
- package/skills/weaver-e10-builder/actionflows/references/components/trigger/WebHookTrigger.md +91 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveAddSign.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveAgreeRejectApply.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveCommit.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveConsulTurnTodo.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveCreate.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveDelete.md +19 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveDoCirculate.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveDoForward.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveDoTurnTodo.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveEntrust.md +19 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveIntervention.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveMandatoryArchiving.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveManualCC.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveRefuseRejectApply.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveRejectApply.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveSave.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveSendBack.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveShareEntry.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveTrigger.md +99 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/ApproveWithdraw.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/WorkFlowDocEmpowerment.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/components/workflow/WorkflowToDoc.md +17 -0
- package/skills/weaver-e10-builder/actionflows/references/condition_rules.md +100 -0
- package/skills/weaver-e10-builder/actionflows/references/dynamic_capability_matrix.md +39 -0
- package/skills/weaver-e10-builder/actionflows/references/dynamic_resources.md +41 -0
- package/skills/weaver-e10-builder/actionflows/references/examples/enquiry-form-batch-insert-scene2.json +1043 -0
- package/skills/weaver-e10-builder/actionflows/references/function_rules.md +15 -0
- package/skills/weaver-e10-builder/actionflows/references/trigger_runtime_notes.md +53 -0
- package/skills/weaver-e10-builder/assets/dom-structure/Bar.json +341 -0
- package/skills/weaver-e10-builder/assets/dom-structure/BarStack.json +341 -0
- package/skills/weaver-e10-builder/assets/dom-structure/Bubble.json +323 -0
- package/skills/weaver-e10-builder/assets/dom-structure/Calendar.json +515 -0
- package/skills/weaver-e10-builder/assets/dom-structure/Circular.json +337 -0
- package/skills/weaver-e10-builder/assets/dom-structure/CollapsePanel.json +289 -0
- package/skills/weaver-e10-builder/assets/dom-structure/Comment.json +617 -0
- package/skills/weaver-e10-builder/assets/dom-structure/CountDown.json +755 -0
- package/skills/weaver-e10-builder/assets/dom-structure/DigitalPanel.json +191 -0
- package/skills/weaver-e10-builder/assets/dom-structure/EbButton.json +387 -0
- package/skills/weaver-e10-builder/assets/dom-structure/FastCreate.json +242 -0
- package/skills/weaver-e10-builder/assets/dom-structure/Gauge.json +282 -0
- package/skills/weaver-e10-builder/assets/dom-structure/HBar.json +336 -0
- package/skills/weaver-e10-builder/assets/dom-structure/HBarStack.json +337 -0
- package/skills/weaver-e10-builder/assets/dom-structure/Line.json +341 -0
- package/skills/weaver-e10-builder/assets/dom-structure/NList.json +712 -0
- package/skills/weaver-e10-builder/assets/dom-structure/NavBar.json +274 -0
- package/skills/weaver-e10-builder/assets/dom-structure/NavPanel.json +390 -0
- package/skills/weaver-e10-builder/assets/dom-structure/NewTab.json +606 -0
- package/skills/weaver-e10-builder/assets/dom-structure/Nightingale.json +336 -0
- package/skills/weaver-e10-builder/assets/dom-structure/PageHeader.json +205 -0
- package/skills/weaver-e10-builder/assets/dom-structure/Picture.json +209 -0
- package/skills/weaver-e10-builder/assets/dom-structure/Pie.json +338 -0
- package/skills/weaver-e10-builder/assets/dom-structure/ProgressChart.json +299 -0
- package/skills/weaver-e10-builder/assets/dom-structure/SearchGlobal.json +628 -0
- package/skills/weaver-e10-builder/assets/dom-structure/Slide.json +489 -0
- package/skills/weaver-e10-builder/assets/dom-structure/Treemap.json +324 -0
- package/skills/weaver-e10-builder/assets/factory/chart-dimensions.json +536 -0
- package/skills/weaver-e10-builder/assets/factory/example-btn-progress-collapse-configured.json +2515 -0
- package/skills/weaver-e10-builder/assets/factory/example-configured-2.json +13805 -0
- package/skills/weaver-e10-builder/assets/factory/example-configured.json +6735 -0
- package/skills/weaver-e10-builder/assets/factory/factory-bar-stack.json +326 -0
- package/skills/weaver-e10-builder/assets/factory/factory-bar.json +222 -0
- package/skills/weaver-e10-builder/assets/factory/factory-bubble.json +322 -0
- package/skills/weaver-e10-builder/assets/factory/factory-calendar.json +325 -0
- package/skills/weaver-e10-builder/assets/factory/factory-circular.json +320 -0
- package/skills/weaver-e10-builder/assets/factory/factory-collapse-panel.json +132 -0
- package/skills/weaver-e10-builder/assets/factory/factory-comment.json +388 -0
- package/skills/weaver-e10-builder/assets/factory/factory-count-down.json +198 -0
- package/skills/weaver-e10-builder/assets/factory/factory-digital-panel.json +108 -0
- package/skills/weaver-e10-builder/assets/factory/factory-eb-button.json +150 -0
- package/skills/weaver-e10-builder/assets/factory/factory-fast-create.json +62 -0
- package/skills/weaver-e10-builder/assets/factory/factory-gauge.json +312 -0
- package/skills/weaver-e10-builder/assets/factory/factory-h-bar-stack.json +328 -0
- package/skills/weaver-e10-builder/assets/factory/factory-h-bar.json +326 -0
- package/skills/weaver-e10-builder/assets/factory/factory-line.json +212 -0
- package/skills/weaver-e10-builder/assets/factory/factory-nav-bar.json +167 -0
- package/skills/weaver-e10-builder/assets/factory/factory-nav-menu.json +144 -0
- package/skills/weaver-e10-builder/assets/factory/factory-nav-panel.json +338 -0
- package/skills/weaver-e10-builder/assets/factory/factory-new-tab.json +163 -0
- package/skills/weaver-e10-builder/assets/factory/factory-nightingale.json +312 -0
- package/skills/weaver-e10-builder/assets/factory/factory-nlist.json +112 -0
- package/skills/weaver-e10-builder/assets/factory/factory-page-header.json +171 -0
- package/skills/weaver-e10-builder/assets/factory/factory-picture.json +169 -0
- package/skills/weaver-e10-builder/assets/factory/factory-pie.json +212 -0
- package/skills/weaver-e10-builder/assets/factory/factory-progress-chart.json +162 -0
- package/skills/weaver-e10-builder/assets/factory/factory-search-global.json +104 -0
- package/skills/weaver-e10-builder/assets/factory/factory-slide.json +164 -0
- package/skills/weaver-e10-builder/assets/factory/factory-treemap.json +322 -0
- package/skills/weaver-e10-builder/assets/icons.db +0 -0
- package/skills/weaver-e10-builder/assets/sample/.claude/settings.local.json +8 -0
- package/skills/weaver-e10-builder/assets/sample/api/formApi.js +510 -0
- package/skills/weaver-e10-builder/assets/sample/config/config.js +0 -0
- package/skills/weaver-e10-builder/assets/sample/config/configLoad.js +0 -0
- package/skills/weaver-e10-builder/assets/sample/config/configLoad_default.js +0 -0
- package/skills/weaver-e10-builder/assets/sample/config/config_default.js +0 -0
- package/skills/weaver-e10-builder/assets/sample/entry.js +22 -0
- package/skills/weaver-e10-builder/assets/sample/eslint.config.cjs +48 -0
- package/skills/weaver-e10-builder/assets/sample/memo.md +0 -0
- package/skills/weaver-e10-builder/assets/sample/readme.js +8 -0
- package/skills/weaver-e10-builder/references/app/guide-app-publish.md +92 -0
- package/skills/weaver-e10-builder/references/auth/guide-auth.md +88 -0
- package/skills/weaver-e10-builder/references/coding/guide-edit-backfill.md +189 -0
- package/skills/weaver-e10-builder/references/coding/guide-form-crud.md +262 -0
- package/skills/weaver-e10-builder/references/coding/guide-page-code.md +244 -0
- package/skills/weaver-e10-builder/references/coding/guide-page-export.md +119 -0
- package/skills/weaver-e10-builder/references/coding/ref-compile-rules.md +130 -0
- package/skills/weaver-e10-builder/references/common/guide-plan-template.md +164 -0
- package/skills/weaver-e10-builder/references/common/map.md +153 -0
- package/skills/weaver-e10-builder/references/common/ref-cli-commands.md +635 -0
- package/skills/weaver-e10-builder/references/components/@weapp-Button.md +104 -0
- package/skills/weaver-e10-builder/references/components/base-Badge.md +100 -0
- package/skills/weaver-e10-builder/references/components/base-Dialog.md +358 -0
- package/skills/weaver-e10-builder/references/components/base-Empty.md +58 -0
- package/skills/weaver-e10-builder/references/components/base-Tag.md +112 -0
- package/skills/weaver-e10-builder/references/components/display-Alert.md +64 -0
- package/skills/weaver-e10-builder/references/components/display-Avatar.md +150 -0
- package/skills/weaver-e10-builder/references/components/display-Calendar.md +263 -0
- package/skills/weaver-e10-builder/references/components/display-Carousel.md +115 -0
- package/skills/weaver-e10-builder/references/components/display-Collapse.md +299 -0
- package/skills/weaver-e10-builder/references/components/display-FilePreview.md +49 -0
- package/skills/weaver-e10-builder/references/components/display-Icon.md +66 -0
- package/skills/weaver-e10-builder/references/components/display-List.md +320 -0
- package/skills/weaver-e10-builder/references/components/display-Pagination.md +41 -0
- package/skills/weaver-e10-builder/references/components/display-Spin.md +34 -0
- package/skills/weaver-e10-builder/references/components/display-Steps.md +89 -0
- package/skills/weaver-e10-builder/references/components/display-Table.md +160 -0
- package/skills/weaver-e10-builder/references/components/display-Title.md +117 -0
- package/skills/weaver-e10-builder/references/components/form-Checkbox.md +161 -0
- package/skills/weaver-e10-builder/references/components/form-DepartmentBrowser-api.md +52 -0
- package/skills/weaver-e10-builder/references/components/form-EmployeeBrowser-api.md +51 -0
- package/skills/weaver-e10-builder/references/components/form-EmployeeBrowser.md +51 -0
- package/skills/weaver-e10-builder/references/components/form-Input.md +123 -0
- package/skills/weaver-e10-builder/references/components/form-Radio.md +145 -0
- package/skills/weaver-e10-builder/references/components/form-Select.md +191 -0
- package/skills/weaver-e10-builder/references/components/form-Switch.md +46 -0
- package/skills/weaver-e10-builder/references/components/form-Upload.md +53 -0
- package/skills/weaver-e10-builder/references/components/generic-Echarts.md +102 -0
- package/skills/weaver-e10-builder/references/ebuilder-designer/guide-designer-components.md +130 -0
- package/skills/weaver-e10-builder/references/ebuilder-designer/guide-designer-css.md +127 -0
- package/skills/weaver-e10-builder/references/ebuilder-designer/guide-designer-factory.md +460 -0
- package/skills/weaver-e10-builder/references/ebuilder-designer/guide-designer-version.md +111 -0
- package/skills/weaver-e10-builder/references/ebuilder-designer/guide-designer.md +288 -0
- package/skills/weaver-e10-builder/references/esb-interface/guide-import.md +34 -0
- package/skills/weaver-e10-builder/references/form/guide-create-form.md +248 -0
- package/skills/weaver-e10-builder/references/form/guide-ebuilder-filter.md +73 -0
- package/skills/weaver-e10-builder/references/form/guide-ebuilder-scope.md +82 -0
- package/skills/weaver-e10-builder/references/form/guide-field-linkage.md +123 -0
- package/skills/weaver-e10-builder/references/form/guide-form-archive-permission.md +175 -0
- package/skills/weaver-e10-builder/references/form/guide-form-association.md +124 -0
- package/skills/weaver-e10-builder/references/form/guide-form-button.md +169 -0
- package/skills/weaver-e10-builder/references/form/guide-form-data.md +78 -0
- package/skills/weaver-e10-builder/references/form/guide-form-formula-functions.md +343 -0
- package/skills/weaver-e10-builder/references/form/guide-form-layout-incremental.md +90 -0
- package/skills/weaver-e10-builder/references/form/guide-form-layout-planning.md +68 -0
- package/skills/weaver-e10-builder/references/form/guide-form-linkage.md +269 -0
- package/skills/weaver-e10-builder/references/form/guide-form-message.md +74 -0
- package/skills/weaver-e10-builder/references/form/guide-form-physical-table.md +146 -0
- package/skills/weaver-e10-builder/references/form/guide-form-serial-mark.md +47 -0
- package/skills/weaver-e10-builder/references/form/guide-form-sub-detail.md +82 -0
- package/skills/weaver-e10-builder/references/form/guide-form-view-permission.md +38 -0
- package/skills/weaver-e10-builder/references/form/guide-form-view.md +371 -0
- package/skills/weaver-e10-builder/references/form/guide-formula-linkage.md +281 -0
- package/skills/weaver-e10-builder/references/form/guide-list-columns.md +52 -0
- package/skills/weaver-e10-builder/references/form/guide-list-custom-text.md +52 -0
- package/skills/weaver-e10-builder/references/form/guide-list-stats.md +136 -0
- package/skills/weaver-e10-builder/references/form/guide-virtual-form.md +156 -0
- package/skills/weaver-e10-builder/references/form/ref-form-fields.md +293 -0
- package/skills/weaver-e10-builder/references/form/style-templates.md +97 -0
- package/skills/weaver-e10-builder/references/hrm/guide-matrix.md +245 -0
- package/skills/weaver-e10-builder/references/hrm/guide-org-employee.md +155 -0
- package/skills/weaver-e10-builder/references/menu/system-menus.md +75 -0
- package/skills/weaver-e10-builder/references/report/add-dataset-registration-guide.md +139 -0
- package/skills/weaver-e10-builder/references/report/ai-report-workflow.md +412 -0
- package/skills/weaver-e10-builder/references/report/api-report-build-fast-path.md +275 -0
- package/skills/weaver-e10-builder/references/report/app-datasource-lookup-guide.md +230 -0
- package/skills/weaver-e10-builder/references/report/cell-config-echo-guide.md +163 -0
- package/skills/weaver-e10-builder/references/report/cell-transform-guide.md +147 -0
- package/skills/weaver-e10-builder/references/report/condition-format-guide.md +140 -0
- package/skills/weaver-e10-builder/references/report/cross-dataset-filter-guide.md +304 -0
- package/skills/weaver-e10-builder/references/report/dataset-query-filter-guide.md +235 -0
- package/skills/weaver-e10-builder/references/report/dataset-sidebar-ops-guide.md +280 -0
- package/skills/weaver-e10-builder/references/report/dataset-table-field-contract-guide.md +339 -0
- package/skills/weaver-e10-builder/references/report/datasource-metadata-guide.md +365 -0
- package/skills/weaver-e10-builder/references/report/datasource-selection-and-parent-filter-guide.md +148 -0
- package/skills/weaver-e10-builder/references/report/date-range-query-reference.md +102 -0
- package/skills/weaver-e10-builder/references/report/default-header-style-guide.md +70 -0
- package/skills/weaver-e10-builder/references/report/designer-blank-prevention-guide.md +111 -0
- package/skills/weaver-e10-builder/references/report/event-hreflink-guide.md +184 -0
- package/skills/weaver-e10-builder/references/report/field-bind-exact-match-guide.md +208 -0
- package/skills/weaver-e10-builder/references/report/formula-cell-api-guide.md +258 -0
- package/skills/weaver-e10-builder/references/report/guide-report-build.md +131 -0
- package/skills/weaver-e10-builder/references/report/guide-report-modify.md +100 -0
- package/skills/weaver-e10-builder/references/report/guide-report-multisource.md +143 -0
- package/skills/weaver-e10-builder/references/report/guide-report-query.md +98 -0
- package/skills/weaver-e10-builder/references/report/hidden-row-and-header-merge-guide.md +100 -0
- package/skills/weaver-e10-builder/references/report/layout-showlocation-freeze-guide.md +167 -0
- package/skills/weaver-e10-builder/references/report/preaggregate-auto-disable-guide.md +107 -0
- package/skills/weaver-e10-builder/references/report/query-condition-api-guide.md +890 -0
- package/skills/weaver-e10-builder/references/report/ref-report-commands.md +122 -0
- package/skills/weaver-e10-builder/references/report/ref-report-pitfalls.md +226 -0
- package/skills/weaver-e10-builder/references/report/report-baseinfo-defaults-guide.md +117 -0
- package/skills/weaver-e10-builder/references/report/report-building-guide.md +511 -0
- package/skills/weaver-e10-builder/references/report/report-config-schema.md +445 -0
- package/skills/weaver-e10-builder/references/report/report-create-modes-guide.md +182 -0
- package/skills/weaver-e10-builder/references/report/report-data-model.md +447 -0
- package/skills/weaver-e10-builder/references/report/report-delivery-contract.md +101 -0
- package/skills/weaver-e10-builder/references/report/report-designer-feature-map.md +500 -0
- package/skills/weaver-e10-builder/references/report/report-internal-error-guide.md +78 -0
- package/skills/weaver-e10-builder/references/report/report-knowledge-base.md +389 -0
- package/skills/weaver-e10-builder/references/report/report-lifecycle-api-guide.md +392 -0
- package/skills/weaver-e10-builder/references/report/report-list-page-ops-guide.md +191 -0
- package/skills/weaver-e10-builder/references/report/report-permission-guide.md +365 -0
- package/skills/weaver-e10-builder/references/report/report-requirement-analysis-template.md +202 -0
- package/skills/weaver-e10-builder/references/report/report-self-check-guide.md +164 -0
- package/skills/weaver-e10-builder/references/report/safe-partial-save-guide.md +151 -0
- package/skills/weaver-e10-builder/references/report/snowflake-id-precision-guide.md +84 -0
- package/skills/weaver-e10-builder/references/report/spec-build-schema.md +294 -0
- package/skills/weaver-e10-builder/references/report/targeted-fix-guide.md +97 -0
- package/skills/weaver-e10-builder/references/report/user-request-scope-only-guide.md +82 -0
- package/skills/weaver-e10-builder/references/workflow/guide-function-management.md +154 -0
- package/skills/weaver-e10-builder/references/workflow/guide-opinion-settings.md +126 -0
- package/skills/weaver-e10-builder/references/workflow/guide-workflow-action.md +174 -0
- package/skills/weaver-e10-builder/references/workflow/guide-workflow-auth-resp.md +224 -0
- package/skills/weaver-e10-builder/references/workflow/guide-workflow-condition.md +447 -0
- package/skills/weaver-e10-builder/references/workflow/guide-workflow-node-layout.md +181 -0
- package/skills/weaver-e10-builder/references/workflow/guide-workflow-odoc-setting.md +248 -0
- package/skills/weaver-e10-builder/references/workflow/guide-workflow-odoc.md +68 -0
- package/skills/weaver-e10-builder/references/workflow/guide-workflow.md +527 -0
- package/skills/weaver-e10-builder/references/workflow/operator-matrix.md +76 -0
- package/skills/weaver-e10-caizhilian/SKILL.md +14 -4
- package/skills/weaver-e10-caizhilian/references/file-upload.md +100 -295
- package/skills/weaver-e10-caizhilian/references/files.md +15 -0
- package/skills/weaver-e10-caizhilian/references/folder.md +31 -3
- package/skills/weaver-e10-caizhilian/references/setting-attach.md +48 -3
- package/skills/weaver-e10-caizhilian/references/source-manifest.json +634 -25
- package/skills/weaver-e10-jiuchuanhui/SKILL.md +9 -1
- package/skills/weaver-e10-shared/SKILL.md +19 -5
- package/skills/weaver-e10-shared/references/e10-auth-and-session.md +25 -5
- package/skills/weaver-e10-workflow/SKILL.md +28 -47
- package/skills/weaver-e10-workflow/references/source-manifest.json +46 -36
- package/skills/weaver-e10-workflow/references/workflow-batch.md +2 -4
- package/skills/weaver-e10-workflow/references/workflow-create.md +261 -86
- package/skills/weaver-e10-workflow/references/workflow-edit.md +2 -1
- package/skills/weaver-e10-workflow/references/workflow-memory.md +3 -6
- package/skills/weaver-e10-workflow/references/workflow-operate.md +2 -1
- package/skills/weaver-e10-workflow/references/workflow-query.md +11 -9
- package/skills/weaver-e10-workflow/references/workflow-share.md +2 -0
package/README.md
CHANGED
|
@@ -211,22 +211,30 @@ weaver-work-cli auth login --base-url "https://weapp.xxx.cn"
|
|
|
211
211
|
weaver-work-cli auth oidc --base-url "https://weapp.xxx.cn"
|
|
212
212
|
```
|
|
213
213
|
|
|
214
|
-
|
|
214
|
+
只有当前智能体身份明确为 XiaoE 时,`auth xiaoe` 和未显式指定认证来源的业务命令才会优先使用平台注入的
|
|
215
215
|
`XIAOE_USER_TOKEN` + `XIAOE_DOMAIN` 换取 ETEAMSID:其中 `XIAOE_DOMAIN` 是
|
|
216
216
|
XiaoE/erpa 换票服务地址,不是 E10 登录地址。CLI 的 Node 实现会直接调用与
|
|
217
217
|
`xiaoe_env.py` / `tokens.py` 相同的换票接口,并校验业务码和 `data.eteamId`;它保留
|
|
218
218
|
系统 CA 校验,且只允许同源重定向或同主机 HTTP→HTTPS 升级。平台凭证不可用时,
|
|
219
219
|
CLI 会先在内部调用 npm 包自带的 `scripts/xiaoe_env.py` 兼容路径,再按顺序尝试
|
|
220
220
|
宿主 `xiaoeUserData/tokens.py`、桌面 XiaoE 客户端当前会话
|
|
221
|
-
|
|
221
|
+
(优先读取宿主注入的 `XIAOE_USER_SETTINGS_PATH`,其次查找
|
|
222
|
+
`XIAOE_ROBOT_DATA_ROOT` / `XIAOE_ROBOT_ROOT`,最后回退
|
|
223
|
+
`XiaoE/Robots/<id>/user_settings.json`)和 `WEAVER_XIAOE_*` 环境映射。只要会话文件中的
|
|
224
|
+
`session_id` 与 `erpa` 有效,Node 路径即可直接换票,不要求宿主存在 `tokens.py`。
|
|
222
225
|
`xiaoe_env.py` 由 CLI 独占执行并解析,不放进 shared Skill,也不把 stdout 凭证暴露给
|
|
223
226
|
Agent;Skill 只负责调用 `weaver-work-cli auth xiaoe`。CLI 自带脚本仅依赖 Python
|
|
224
227
|
标准库,仍保持 TLS 证书校验,不会采用关闭证书校验的回退。
|
|
225
228
|
|
|
229
|
+
XiaoE 桌面客户端不一定注入上述 Token 对;它会注入 `XIAOE_DATA_ROOT`、
|
|
230
|
+
`XIAOE_ROBOT_DATA_ROOT`、`XIAOE_USER_SETTINGS_PATH`、`XIAOE_ROBOT_ROOT` 等精确的
|
|
231
|
+
运行时路径标记,CLI 也把这些标记识别为当前 XiaoE 桌面宿主。普通 `XIAOE_SKILL_*`、
|
|
232
|
+
`WEAVER_XIAOE_*` 配置或仅在磁盘上发现客户端文件仍不构成宿主身份。
|
|
233
|
+
|
|
226
234
|
E10 目标地址按“显式 `--base-url` → 专用 `WEAVER_XIAOE_*` E10 配置/映射 →
|
|
227
235
|
当前 profile → `https://www.e-cology.com.cn`”解析,绝不会把 `XIAOE_DOMAIN`
|
|
228
236
|
当作 E10 地址。匹配成功时直接保存登录态,并固定使用 `agentType=XiaoE`。业务命令
|
|
229
|
-
|
|
237
|
+
在已确认的 XiaoE 智能体环境中且未显式指定 `--auth` / `--profile` 时,也会自动优先尝试 XiaoE 统一登录。
|
|
230
238
|
`auth xiaoe` 失败后仅在 macOS/Windows 桌面宿主自动降级浏览器 OAuth;Web/Linux
|
|
231
239
|
环境会返回结构化的 `authentication/xiaoe_web_credential_unavailable` 错误,不再
|
|
232
240
|
启动无法回调的 localhost 浏览器登录。确需浏览器授权时,应在可接收本地回调的宿主
|
|
@@ -236,6 +244,9 @@ E10 目标地址按“显式 `--base-url` → 专用 `WEAVER_XIAOE_*` E10 配置
|
|
|
236
244
|
weaver-work-cli auth xiaoe
|
|
237
245
|
```
|
|
238
246
|
|
|
247
|
+
`auth login` / `auth oidc` 始终是纯浏览器 OAuth 入口。本机存在 `xiaoeUserData/tokens.py`、XiaoE 客户端目录、`XIAOE_SKILL_*` 或 `WEAVER_XIAOE_*` 配置,都不能单独证明当前智能体是 XiaoE,也不会让 WorkBuddy、Codex 或其他智能体切换到 XiaoE 登录。
|
|
248
|
+
`auth xiaoe` 会先输出不含凭证的 preflight 摘要(`hostDetected`、`attempted`、`tokenScriptDetected`、`clientSettingsDetected`、`baseUrl`);命中 `tokens.py` 或内置 Node 客户端会话路径时还会输出明确的尝试日志。统一登录成功后,登录结果以及后续 `auth status` 会显示 `credentialSourceStep`、`credentialSourceType`、`credentialSourceLabel`,可据此确认实际凭证来源;`3 / xiaoe_client / XiaoE client settings` 表示未依赖 `tokens.py`,由 Node 直接换票。
|
|
249
|
+
|
|
239
250
|
默认本地回调地址为 `http://127.0.0.1:19800/callback`。如果端口被占用:
|
|
240
251
|
|
|
241
252
|
```text
|
|
@@ -252,6 +263,25 @@ weaver-work-cli auth login --base-url "https://weapp.xxx.cn" --port 19801
|
|
|
252
263
|
weaver-work-cli auth login --base-url "https://weapp.xxx.cn" --agent_type workbuddy
|
|
253
264
|
```
|
|
254
265
|
|
|
266
|
+
浏览器授权成功后,本地回调页会为已识别的桌面智能体显示应用打开弹层。CLI 内置
|
|
267
|
+
WorkBuddy(`workbuddy://`)、智能小 E(`xiaoe-client://`)和 Codex(`codex://`)映射;
|
|
268
|
+
其他智能体在 `agent_type` 本身是合法协议名时,默认按 `<agent_type>://` 唤起。弹层显示
|
|
269
|
+
“打开客户端 / 始终打开客户端 / 取消”。用户确认后,页面通过一次性令牌请求本地 CLI,
|
|
270
|
+
由 CLI 调用系统注册的桌面协议;浏览器不直接访问自定义
|
|
271
|
+
协议,因此不会再出现 Chrome/Edge 无法定制的外部协议确认框。Windows/macOS 安装包都
|
|
272
|
+
需要注册该协议。如果宿主要返回当前会话等更精确的位置,可传入宿主
|
|
273
|
+
注册的深链(仅接受桌面应用自定义协议,不接受网页、脚本或本地文件 URL):
|
|
274
|
+
|
|
275
|
+
```text
|
|
276
|
+
weaver-work-cli auth login --base-url "https://weapp.xxx.cn" --agent_type workbuddy --agent-return-url "workbuddy://<宿主提供的路径>"
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
宿主也可以注入 `WEAVER_AGENT_RETURN_URL`,命令行参数优先于环境变量;客户端协议名与
|
|
280
|
+
`agent_type` 不一致时也应使用该覆盖。“始终打开”偏好
|
|
281
|
+
保存在当前本地回调地址的浏览器存储中;未识别到可用返回协议时,回调页保持原有提示,
|
|
282
|
+
不显示应用打开弹层。本地 CLI 打开通道默认保留 15 分钟;超过时间再点击时会自动退回
|
|
283
|
+
浏览器自定义协议打开方式,仍可打开应用,但浏览器可能重新显示原生协议确认框。
|
|
284
|
+
|
|
255
285
|
方式二:手动写入浏览器中的 `ETEAMSID`。
|
|
256
286
|
|
|
257
287
|
```text
|
package/dist/core/output.js
CHANGED
|
@@ -233,6 +233,58 @@ function fitEnvelope(value, leading, extraWarnings, budgetBytes) {
|
|
|
233
233
|
warnings: [...extraWarnings, 'stdout_compacted'],
|
|
234
234
|
};
|
|
235
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* stdout 序列化:默认 `JSON.stringify(value, null, 2)`;给了 `compactPaths` 时,**只有**命中这些
|
|
238
|
+
* 路径的子树改成单行(紧凑)输出,其余照旧缩进。
|
|
239
|
+
*
|
|
240
|
+
* 为什么需要它:像 `historyRequestData` 这种「每条都长、层级又深」的数组,缩进空白能吃掉近 1/4
|
|
241
|
+
* 体积(真机实测:该键 13,017 B → 9,835 B,整份 21,620 B → 18,438 B),而它对读模型的**可读性
|
|
242
|
+
* 收益为零**——模型要的是"哪条历史、哪个字段、什么值",不是每层两个空格。
|
|
243
|
+
*
|
|
244
|
+
* **内容一字不改**:输出仍是合法 JSON,parse 出来的对象与全缩进版**完全一致**(只是空白不同),
|
|
245
|
+
* 消费端不需要任何改动;结构也保持数组/对象原样,不会退化成"需要再 parse 一次的字符串"。
|
|
246
|
+
*
|
|
247
|
+
* 路径口径:从信封根算起的点分路径(如 `data.historyRequestData`),**精确匹配**、不递归下钻。
|
|
248
|
+
* 实现用「占位符摘出 → 紧凑序列化 → 文本替换回填」,而**不是**自己递归拼 JSON:标量转义、
|
|
249
|
+
* `undefined` 键丢弃、数组里 `undefined` 补 `null`、`toJSON` 这些细节全部沿用 `JSON.stringify`
|
|
250
|
+
* 的原生行为,避免手写序列化器在边角上与原输出分叉。
|
|
251
|
+
*/
|
|
252
|
+
export function stringifyForStdout(value, compactPaths) {
|
|
253
|
+
const wanted = new Set((compactPaths ?? []).filter((path) => typeof path === 'string' && path !== ''));
|
|
254
|
+
const plain = JSON.stringify(value, null, 2);
|
|
255
|
+
if (!wanted.size || plain === undefined)
|
|
256
|
+
return plain;
|
|
257
|
+
// 占位符必须不可能与真实内容撞车:随机盐 + 对已序列化文本做一次包含检查(撞了就换一个)。
|
|
258
|
+
let salt = '';
|
|
259
|
+
do {
|
|
260
|
+
salt = `__WEAVER_COMPACT_${Math.random().toString(36).slice(2, 12)}__`;
|
|
261
|
+
} while (plain.includes(salt));
|
|
262
|
+
const compacted = [];
|
|
263
|
+
const swap = (node, path) => {
|
|
264
|
+
if (node !== null && typeof node === 'object' && wanted.has(path)) {
|
|
265
|
+
const inline = JSON.stringify(node);
|
|
266
|
+
if (inline !== undefined) {
|
|
267
|
+
compacted.push(inline);
|
|
268
|
+
return `${salt}${compacted.length - 1}__`;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (Array.isArray(node))
|
|
272
|
+
return node.map((item, index) => swap(item, `${path}[${index}]`));
|
|
273
|
+
if (node !== null && typeof node === 'object') {
|
|
274
|
+
const out = {};
|
|
275
|
+
for (const [key, item] of Object.entries(node)) {
|
|
276
|
+
out[key] = swap(item, path ? `${path}.${key}` : key);
|
|
277
|
+
}
|
|
278
|
+
return out;
|
|
279
|
+
}
|
|
280
|
+
return node;
|
|
281
|
+
};
|
|
282
|
+
const swapped = JSON.stringify(swap(value, ''), null, 2);
|
|
283
|
+
if (typeof swapped !== 'string')
|
|
284
|
+
return swapped;
|
|
285
|
+
// 占位符在文本里是一个普通字符串字面量(`"__WEAVER_COMPACT_xxx__0__"`),整体替换成紧凑 JSON。
|
|
286
|
+
return swapped.replace(new RegExp(`"${salt}(\\d+)__"`, 'g'), (_match, index) => compacted[Number(index)] ?? 'null');
|
|
287
|
+
}
|
|
236
288
|
export class Output {
|
|
237
289
|
ctx;
|
|
238
290
|
constructor(ctx) {
|
|
@@ -245,7 +297,7 @@ export class Output {
|
|
|
245
297
|
console.log(options.text);
|
|
246
298
|
return;
|
|
247
299
|
}
|
|
248
|
-
console.log(
|
|
300
|
+
console.log(stringifyForStdout(this.prepare(value, options), options.compactPaths));
|
|
249
301
|
}
|
|
250
302
|
prepare(value, options) {
|
|
251
303
|
const threshold = resultThresholdBytes(this.ctx);
|
|
@@ -1,16 +1,54 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process';
|
|
2
|
+
import { randomBytes } from 'node:crypto';
|
|
2
3
|
import { createServer } from 'node:http';
|
|
3
4
|
import { CliError, ExitCode } from '../../../core/errors.js';
|
|
4
5
|
import { clearInvoiceTokenForSession } from '../../../shortcuts/invoice/host.js';
|
|
5
6
|
import { buildE10CookieHeader, E10AuthSession, clearProfileAuthFile, extractRawSetCookie, extractSessionTicket, findAuthFile, getActiveProfile, getProfileAuthPath, getProfileDir, listProfiles, profileNameFromUrl, readProfileConfig, readTeamsCheckUserInfo, saveAuthFile, saveProfileConfig, setActiveProfile, switchActiveProfile, } from './session.js';
|
|
6
7
|
import { getE10AuthRoot } from './paths.js';
|
|
7
|
-
import { XIAOE_AGENT_TYPE, createXiaoEUnifiedLoginUnavailableError, hasXiaoEEnv, resolveXiaoEPreferredBaseUrl, shouldUseXiaoEBrowserFallback, tryXiaoEUnifiedLogin as tryXiaoEUnifiedSessionLogin, } from './xiaoe.js';
|
|
8
|
+
import { XIAOE_AGENT_TYPE, createXiaoEUnifiedLoginUnavailableError, hasXiaoEClientCredential, hasXiaoEEnv, hasXiaoETokenScript, resolveXiaoEPreferredBaseUrl, shouldUseXiaoEBrowserFallback, tryXiaoEUnifiedLogin as tryXiaoEUnifiedSessionLogin, } from './xiaoe.js';
|
|
8
9
|
export { DEFAULT_E10_BASE_URL, XIAOE_AGENT_TYPE, hasXiaoEEnv, hasXiaoETokenScript, resolveXiaoEDefaultBaseUrl, resolveXiaoEPreferredBaseUrl, resolveXiaoEUnifiedLoginCredential, shouldUseXiaoEBrowserFallback, } from './xiaoe.js';
|
|
9
10
|
const DEFAULT_AGENT_TYPE = 'weaver-work-cli';
|
|
10
11
|
const EXPLICIT_AGENT_TYPE_ENV_KEYS = [
|
|
11
|
-
'WEAVER_AGENT_TYPE',
|
|
12
12
|
'WORKBUDDY_AGENT_TYPE',
|
|
13
13
|
'CODEX_AGENT_TYPE',
|
|
14
|
+
'WEAVER_AGENT_TYPE',
|
|
15
|
+
];
|
|
16
|
+
const AGENT_RETURN_URL_ENV_KEY = 'WEAVER_AGENT_RETURN_URL';
|
|
17
|
+
const AGENT_RETURN_PATH = '/agent-return';
|
|
18
|
+
const AGENT_RETURN_TOKEN_HEADER = 'x-weaver-agent-return-token';
|
|
19
|
+
const AGENT_RETURN_TIMEOUT_MS = 900_000;
|
|
20
|
+
const UNSAFE_AGENT_RETURN_PROTOCOLS = new Set([
|
|
21
|
+
'about:',
|
|
22
|
+
'blob:',
|
|
23
|
+
'data:',
|
|
24
|
+
'file:',
|
|
25
|
+
'ftp:',
|
|
26
|
+
'http:',
|
|
27
|
+
'https:',
|
|
28
|
+
'javascript:',
|
|
29
|
+
'mailto:',
|
|
30
|
+
'sms:',
|
|
31
|
+
'tel:',
|
|
32
|
+
'vbscript:',
|
|
33
|
+
'ws:',
|
|
34
|
+
'wss:',
|
|
35
|
+
]);
|
|
36
|
+
const BUILT_IN_AGENT_RETURN_TARGETS = [
|
|
37
|
+
{
|
|
38
|
+
aliases: ['workbuddy'],
|
|
39
|
+
label: 'WorkBuddy',
|
|
40
|
+
url: 'workbuddy://',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
aliases: ['xiaoe', 'xiaoeclient', '小e', '智能小e'],
|
|
44
|
+
label: '智能小 E',
|
|
45
|
+
url: 'xiaoe-client://',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
aliases: ['codex', 'openaicodex'],
|
|
49
|
+
label: 'Codex',
|
|
50
|
+
url: 'codex://',
|
|
51
|
+
},
|
|
14
52
|
];
|
|
15
53
|
function asOptions(value) {
|
|
16
54
|
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
@@ -49,6 +87,59 @@ export function resolveAgentType(options = {}, env = process.env) {
|
|
|
49
87
|
|| inferAgentTypeFromEnv(env)
|
|
50
88
|
|| DEFAULT_AGENT_TYPE;
|
|
51
89
|
}
|
|
90
|
+
function normalizeAgentKey(value) {
|
|
91
|
+
return value.toLowerCase().replace(/[^a-z0-9]+/gu, '');
|
|
92
|
+
}
|
|
93
|
+
function normalizeAgentAlias(value) {
|
|
94
|
+
return value.trim().toLowerCase().replace(/[^\p{Letter}\p{Number}]+/gu, '');
|
|
95
|
+
}
|
|
96
|
+
function builtInAgentReturnTarget(agentType) {
|
|
97
|
+
const alias = normalizeAgentAlias(agentType);
|
|
98
|
+
const target = BUILT_IN_AGENT_RETURN_TARGETS.find((candidate) => candidate.aliases.includes(alias));
|
|
99
|
+
return target ? { label: target.label, url: target.url } : null;
|
|
100
|
+
}
|
|
101
|
+
function conventionalAgentReturnUrl(agentType) {
|
|
102
|
+
const scheme = agentType.trim().toLowerCase();
|
|
103
|
+
if (normalizeAgentAlias(agentType) === normalizeAgentAlias(DEFAULT_AGENT_TYPE)
|
|
104
|
+
|| scheme.length > 64
|
|
105
|
+
|| !/^[a-z][a-z0-9+.-]*$/u.test(scheme)
|
|
106
|
+
|| UNSAFE_AGENT_RETURN_PROTOCOLS.has(`${scheme}:`)) {
|
|
107
|
+
return '';
|
|
108
|
+
}
|
|
109
|
+
return `${scheme}://`;
|
|
110
|
+
}
|
|
111
|
+
function validateAgentReturnUrl(value) {
|
|
112
|
+
if (value.length > 2048
|
|
113
|
+
|| /[\u0000-\u001f\u007f\s]/u.test(value)
|
|
114
|
+
|| !/^[a-z][a-z0-9+.-]*:\/\//iu.test(value)) {
|
|
115
|
+
throw new CliError('Invalid --agent-return-url value', ExitCode.UsageError);
|
|
116
|
+
}
|
|
117
|
+
let url;
|
|
118
|
+
try {
|
|
119
|
+
url = new URL(value);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
throw new CliError('Invalid --agent-return-url value', ExitCode.UsageError);
|
|
123
|
+
}
|
|
124
|
+
if (UNSAFE_AGENT_RETURN_PROTOCOLS.has(url.protocol)) {
|
|
125
|
+
throw new CliError('--agent-return-url must use a registered desktop application URL scheme.', ExitCode.UsageError);
|
|
126
|
+
}
|
|
127
|
+
return value;
|
|
128
|
+
}
|
|
129
|
+
export function resolveAgentReturnTarget(options = {}, env = process.env, agentType = resolveAgentType(options, env)) {
|
|
130
|
+
const builtInTarget = builtInAgentReturnTarget(agentType);
|
|
131
|
+
const explicitUrl = optionString(options, 'agentReturnUrl') || envString(env, AGENT_RETURN_URL_ENV_KEY);
|
|
132
|
+
if (explicitUrl) {
|
|
133
|
+
return {
|
|
134
|
+
label: builtInTarget?.label || agentType,
|
|
135
|
+
url: validateAgentReturnUrl(explicitUrl),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
if (builtInTarget)
|
|
139
|
+
return builtInTarget;
|
|
140
|
+
const conventionalUrl = conventionalAgentReturnUrl(agentType);
|
|
141
|
+
return conventionalUrl ? { label: agentType, url: conventionalUrl } : null;
|
|
142
|
+
}
|
|
52
143
|
function normalizeUrl(value) {
|
|
53
144
|
return value.replace(/\/+$/, '');
|
|
54
145
|
}
|
|
@@ -101,6 +192,10 @@ function formatAuthStatus(status) {
|
|
|
101
192
|
'baseUrl: ' + status.baseUrl,
|
|
102
193
|
'profile: ' + status.profile,
|
|
103
194
|
'authFile: ' + status.authFile,
|
|
195
|
+
...('loginSource' in status && status.loginSource ? ['loginSource: ' + status.loginSource] : []),
|
|
196
|
+
...('credentialSourceStep' in status && status.credentialSourceStep ? ['credentialSourceStep: ' + status.credentialSourceStep] : []),
|
|
197
|
+
...('credentialSourceType' in status && status.credentialSourceType ? ['credentialSourceType: ' + status.credentialSourceType] : []),
|
|
198
|
+
...('credentialSourceLabel' in status && status.credentialSourceLabel ? ['credentialSourceLabel: ' + status.credentialSourceLabel] : []),
|
|
104
199
|
];
|
|
105
200
|
if ('valid' in status) {
|
|
106
201
|
lines.push('valid: ' + String(status.valid));
|
|
@@ -160,8 +255,18 @@ function esc(value) {
|
|
|
160
255
|
.replace(/"/g, '"')
|
|
161
256
|
.replace(/'/g, ''');
|
|
162
257
|
}
|
|
163
|
-
export function renderE10LoginSuccessPage(userId) {
|
|
164
|
-
|
|
258
|
+
export function renderE10LoginSuccessPage(userId, returnTarget = null, launchToken = '') {
|
|
259
|
+
const safeReturnTarget = returnTarget
|
|
260
|
+
? { ...returnTarget, url: validateAgentReturnUrl(returnTarget.url) }
|
|
261
|
+
: null;
|
|
262
|
+
const agentKey = safeReturnTarget ? normalizeAgentKey(safeReturnTarget.label) || 'agent' : '';
|
|
263
|
+
const returnAction = safeReturnTarget && launchToken
|
|
264
|
+
? `<div class="overlay" data-agent-return data-token="${esc(launchToken)}" data-agent-key="${esc(agentKey)}" data-agent-label="${esc(safeReturnTarget.label)}" data-fallback-url="${esc(safeReturnTarget.url)}"><section class="prompt" role="dialog" aria-modal="true" aria-labelledby="agent-return-title"><div class="app-icon" aria-hidden="true"><svg viewBox="0 0 64 64"><defs><linearGradient id="app-gradient" x1="8" y1="4" x2="56" y2="60" gradientUnits="userSpaceOnUse"><stop stop-color="#24d3b5"/><stop offset="1" stop-color="#08aa82"/></linearGradient></defs><rect width="64" height="64" rx="16" fill="url(#app-gradient)"/><path d="M18 21.5 32 13l14 8.5v17L32 47 18 38.5v-17Z" fill="#fff" fill-opacity=".96"/><rect x="23" y="25" width="18" height="15" rx="6" fill="#12b991"/><circle cx="28.5" cy="32.5" r="1.8" fill="#fff"/><circle cx="35.5" cy="32.5" r="1.8" fill="#fff"/></svg></div><h1 id="agent-return-title">是否打开“${esc(safeReturnTarget.label)}”?</h1><p>登录授权已完成,返回 ${esc(safeReturnTarget.label)} 继续使用。</p><button class="primary" type="button" data-action="open">打开“${esc(safeReturnTarget.label)}”</button><button class="secondary" type="button" data-action="always">始终打开“${esc(safeReturnTarget.label)}”</button><button class="secondary" type="button" data-action="cancel">取消</button><div class="status" role="status" aria-live="polite"></div></section></div>`
|
|
265
|
+
: '';
|
|
266
|
+
const returnScript = safeReturnTarget && launchToken
|
|
267
|
+
? `<script nonce="${esc(launchToken)}">(()=>{const root=document.querySelector('[data-agent-return]');if(!root)return;const status=root.querySelector('.status');const buttons=[...root.querySelectorAll('button')];const agentLabel=root.dataset.agentLabel||'应用';const fallbackUrl=root.dataset.fallbackUrl||'';const storageKey='weaver-work-cli.agent-return.'+root.dataset.agentKey;let busy=false;const setBusy=value=>{busy=value;buttons.forEach(button=>{button.disabled=value;});};const closePrompt=()=>{root.hidden=true;};const savePreference=()=>{try{localStorage.setItem(storageKey,'1');}catch{}};const clearPreference=()=>{try{localStorage.removeItem(storageKey);}catch{}};const hasPreference=()=>{try{return localStorage.getItem(storageKey)==='1';}catch{return false;}};const post=async action=>{let response;try{response=await fetch('${AGENT_RETURN_PATH}?action='+encodeURIComponent(action),{method:'POST',headers:{'${AGENT_RETURN_TOKEN_HEADER}':root.dataset.token}});}catch{return false;}if(!response.ok)throw new Error(await response.text()||'请求失败');return true;};const openAgent=async persist=>{if(busy)return;setBusy(true);status.textContent='正在打开 '+agentLabel+'…';try{const openedLocally=await post('open');if(persist)savePreference();if(!openedLocally){closePrompt();window.location.href=fallbackUrl;return;}closePrompt();}catch(error){if(persist)clearPreference();status.textContent=error instanceof Error?error.message:'无法打开应用,请稍后重试。';setBusy(false);}};root.querySelector('[data-action="open"]').addEventListener('click',()=>openAgent(false));root.querySelector('[data-action="always"]').addEventListener('click',()=>openAgent(true));root.querySelector('[data-action="cancel"]').addEventListener('click',()=>{if(busy)return;clearPreference();closePrompt();post('cancel').catch(()=>{});});if(hasPreference())openAgent(false);})();</script>`
|
|
268
|
+
: '';
|
|
269
|
+
return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>weaver-work-cli 登录成功</title><style>:root{color-scheme:light}*{box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Arial,sans-serif;background:radial-gradient(circle at 50% 18%,#eefbf8 0,#f6f7f9 42%,#eef1f5 100%);color:#20242a;display:grid;place-items:center;min-height:100vh;margin:0}.card{background:rgba(255,255,255,.88);border:1px solid #e6e8ec;border-radius:18px;padding:34px 38px;box-shadow:0 18px 55px rgba(18,24,40,.09);width:min(560px,calc(100vw - 40px));text-align:center}.title{font-size:24px;font-weight:700;margin-bottom:10px}.desc{color:#667085;font-size:15px;line-height:24px}.user{color:#98a2b3;font-size:12px;margin-top:18px}.overlay{position:fixed;inset:0;z-index:10;display:grid;place-items:center;padding:20px;background:rgba(28,34,41,.36);backdrop-filter:blur(5px)}.overlay[hidden]{display:none}.prompt{width:min(410px,calc(100vw - 32px));padding:32px 28px 26px;border:1px solid rgba(255,255,255,.75);border-radius:24px;background:rgba(250,250,251,.97);box-shadow:0 24px 70px rgba(15,23,42,.28);text-align:center}.app-icon{width:74px;height:74px;margin:0 auto 24px;filter:drop-shadow(0 8px 14px rgba(8,170,130,.22))}.app-icon svg{display:block;width:100%;height:100%}.prompt h1{margin:0;font-size:20px;line-height:30px;font-weight:700;letter-spacing:-.2px}.prompt p{margin:10px 0 24px;color:#667085;font-size:14px;line-height:22px}.prompt button{display:block;width:100%;min-height:40px;border:0;border-radius:12px;font:600 16px/22px inherit;cursor:pointer;transition:transform .12s ease,filter .12s ease}.prompt button+button{margin-top:10px}.prompt button:hover{filter:brightness(.98)}.prompt button:active{transform:scale(.99)}.prompt button:disabled{cursor:wait;opacity:.62}.primary{background:linear-gradient(180deg,#2f91ff,#0b74e5);color:#fff;box-shadow:0 8px 18px rgba(11,116,229,.2)}.secondary{background:#e9eaec;color:#22252a}.status{min-height:18px;margin-top:14px;color:#667085;font-size:12px;line-height:18px}</style></head><body><main class="card"><div class="title">登录授权成功</div><div class="desc">你可以关闭此页面,返回智能体或终端继续使用。</div><div class="user">${esc(userId)}</div></main>${returnAction}${returnScript}</body></html>`;
|
|
165
270
|
}
|
|
166
271
|
export function resolveBrowserOpenCommand(url, platform = process.platform) {
|
|
167
272
|
if (platform === 'win32') {
|
|
@@ -179,6 +284,17 @@ function openUrlInBrowser(url, ctx) {
|
|
|
179
284
|
}
|
|
180
285
|
});
|
|
181
286
|
}
|
|
287
|
+
function openUrlWithSystemHandler(url) {
|
|
288
|
+
const command = resolveBrowserOpenCommand(url);
|
|
289
|
+
return new Promise((resolve, reject) => {
|
|
290
|
+
execFile(command.file, command.args, (error) => {
|
|
291
|
+
if (error)
|
|
292
|
+
reject(error);
|
|
293
|
+
else
|
|
294
|
+
resolve();
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
}
|
|
182
298
|
export function buildE10AuthorizeUrl(baseUrl, redirectUri, agentType) {
|
|
183
299
|
const authorizeParams = new URLSearchParams({
|
|
184
300
|
redirect_uri: redirectUri,
|
|
@@ -380,11 +496,15 @@ async function runBrowserLogin(ctx, options, behavior = {}) {
|
|
|
380
496
|
const profileFromGlobal = globalOptions.profile;
|
|
381
497
|
const cfg = readProfileConfig(profileFromGlobal || getActiveProfile());
|
|
382
498
|
const explicitBaseUrl = optionString(commandOpts, 'baseUrl') || globalOptions.baseUrl || '';
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
499
|
+
const xiaoEHostDetected = hasXiaoEEnv(ctx.env);
|
|
500
|
+
const useXiaoELogin = behavior.tryXiaoEUnifiedLogin === true && xiaoEHostDetected;
|
|
501
|
+
const baseUrl = useXiaoELogin
|
|
502
|
+
? resolveXiaoEPreferredBaseUrl({
|
|
503
|
+
explicitBaseUrl,
|
|
504
|
+
profileBaseUrl: cfg.baseUrl,
|
|
505
|
+
env: ctx.env,
|
|
506
|
+
})
|
|
507
|
+
: normalizeUrl(explicitBaseUrl || cfg.baseUrl || '');
|
|
388
508
|
const tenantKey = optionString(commandOpts, 'tenantKey');
|
|
389
509
|
const portText = optionString(commandOpts, 'port') || '19800';
|
|
390
510
|
const port = Number.parseInt(portText, 10);
|
|
@@ -393,11 +513,25 @@ async function runBrowserLogin(ctx, options, behavior = {}) {
|
|
|
393
513
|
if (!Number.isInteger(port) || port <= 0 || port > 65535) {
|
|
394
514
|
throw new CliError('Invalid --port value', ExitCode.UsageError);
|
|
395
515
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
516
|
+
if (behavior.tryXiaoEUnifiedLogin) {
|
|
517
|
+
ctx.logger.info([
|
|
518
|
+
'XiaoE unified login preflight:',
|
|
519
|
+
`hostDetected=${String(xiaoEHostDetected)}`,
|
|
520
|
+
`attempted=${String(useXiaoELogin)}`,
|
|
521
|
+
`tokenScriptDetected=${String(hasXiaoETokenScript(ctx.env))}`,
|
|
522
|
+
`clientSettingsDetected=${String(hasXiaoEClientCredential(ctx.env))}`,
|
|
523
|
+
`baseUrl=${baseUrl || '(unresolved)'}`,
|
|
524
|
+
].join(' '));
|
|
525
|
+
}
|
|
526
|
+
if (useXiaoELogin) {
|
|
527
|
+
const xiaoEResult = await tryXiaoEUnifiedLogin(ctx, baseUrl, tenantKey, profileFromGlobal, behavior.allowXiaoETokenScript === true);
|
|
528
|
+
if (xiaoEResult)
|
|
529
|
+
return xiaoEResult;
|
|
530
|
+
}
|
|
531
|
+
const willOpenBrowser = !useXiaoELogin
|
|
532
|
+
|| behavior.browserFallback !== 'desktop-only'
|
|
533
|
+
|| shouldUseXiaoEBrowserFallback();
|
|
534
|
+
if (useXiaoELogin && behavior.explainXiaoEFallback) {
|
|
401
535
|
ctx.logger.warn(xiaoEUnifiedLoginUnavailableMessage(baseUrl, willOpenBrowser));
|
|
402
536
|
}
|
|
403
537
|
if (!willOpenBrowser) {
|
|
@@ -405,6 +539,8 @@ async function runBrowserLogin(ctx, options, behavior = {}) {
|
|
|
405
539
|
}
|
|
406
540
|
if (!baseUrl)
|
|
407
541
|
throw new CliError('Missing --base-url', ExitCode.UsageError);
|
|
542
|
+
const agentReturnTarget = resolveAgentReturnTarget(commandOpts, ctx.env, agentType);
|
|
543
|
+
const agentReturnToken = agentReturnTarget ? randomBytes(24).toString('base64url') : '';
|
|
408
544
|
const redirectUri = `http://127.0.0.1:${port}/callback`;
|
|
409
545
|
const loginUrl = buildE10AuthorizeUrl(baseUrl, redirectUri, agentType);
|
|
410
546
|
ctx.logger.info('Open browser login: ' + loginUrl);
|
|
@@ -412,6 +548,7 @@ async function runBrowserLogin(ctx, options, behavior = {}) {
|
|
|
412
548
|
return await new Promise((resolve, reject) => {
|
|
413
549
|
let settled = false;
|
|
414
550
|
let timer = null;
|
|
551
|
+
let pendingLoginResult = null;
|
|
415
552
|
const finish = (error, result) => {
|
|
416
553
|
if (settled)
|
|
417
554
|
return;
|
|
@@ -433,6 +570,43 @@ async function runBrowserLogin(ctx, options, behavior = {}) {
|
|
|
433
570
|
};
|
|
434
571
|
const server = createServer(async (req, res) => {
|
|
435
572
|
const callbackUrl = new URL(req.url || '/', `http://127.0.0.1:${port}`);
|
|
573
|
+
if (callbackUrl.pathname === AGENT_RETURN_PATH) {
|
|
574
|
+
const requestToken = req.headers[AGENT_RETURN_TOKEN_HEADER];
|
|
575
|
+
if (req.method !== 'POST'
|
|
576
|
+
|| !agentReturnTarget
|
|
577
|
+
|| !pendingLoginResult
|
|
578
|
+
|| requestToken !== agentReturnToken) {
|
|
579
|
+
res.writeHead(403, { 'cache-control': 'no-store', 'content-type': 'text/plain; charset=utf-8' });
|
|
580
|
+
res.end('Forbidden');
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
const action = callbackUrl.searchParams.get('action');
|
|
584
|
+
if (action === 'cancel') {
|
|
585
|
+
const result = pendingLoginResult;
|
|
586
|
+
res.writeHead(204, { 'cache-control': 'no-store' });
|
|
587
|
+
res.end();
|
|
588
|
+
finish(null, result);
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
if (action !== 'open') {
|
|
592
|
+
res.writeHead(400, { 'cache-control': 'no-store', 'content-type': 'text/plain; charset=utf-8' });
|
|
593
|
+
res.end('Invalid action');
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
try {
|
|
597
|
+
await openUrlWithSystemHandler(agentReturnTarget.url);
|
|
598
|
+
const result = pendingLoginResult;
|
|
599
|
+
res.writeHead(200, { 'cache-control': 'no-store', 'content-type': 'application/json; charset=utf-8' });
|
|
600
|
+
res.end('{"ok":true}');
|
|
601
|
+
finish(null, result);
|
|
602
|
+
}
|
|
603
|
+
catch {
|
|
604
|
+
ctx.logger.warn(`Could not open ${agentReturnTarget.label} automatically.`);
|
|
605
|
+
res.writeHead(500, { 'cache-control': 'no-store', 'content-type': 'text/plain; charset=utf-8' });
|
|
606
|
+
res.end(`无法打开 ${agentReturnTarget.label},请确认应用已安装。`);
|
|
607
|
+
}
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
436
610
|
if (callbackUrl.pathname !== '/callback') {
|
|
437
611
|
res.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });
|
|
438
612
|
res.end('Not found');
|
|
@@ -460,9 +634,26 @@ async function runBrowserLogin(ctx, options, behavior = {}) {
|
|
|
460
634
|
}
|
|
461
635
|
try {
|
|
462
636
|
const result = await oidcExchange(code, redirectUri, baseUrl, tenantKey, redirectAgentType, profileFromGlobal);
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
637
|
+
const responseHeaders = {
|
|
638
|
+
'cache-control': 'no-store',
|
|
639
|
+
'content-security-policy': agentReturnTarget
|
|
640
|
+
? `default-src 'none'; style-src 'unsafe-inline'; script-src 'nonce-${agentReturnToken}'; connect-src 'self'`
|
|
641
|
+
: `default-src 'none'; style-src 'unsafe-inline'`,
|
|
642
|
+
'content-type': 'text/html; charset=utf-8',
|
|
643
|
+
'referrer-policy': 'no-referrer',
|
|
644
|
+
'x-content-type-options': 'nosniff',
|
|
645
|
+
'x-frame-options': 'DENY',
|
|
646
|
+
};
|
|
647
|
+
res.writeHead(200, responseHeaders);
|
|
648
|
+
res.end(renderE10LoginSuccessPage(result.userId, agentReturnTarget, agentReturnToken));
|
|
649
|
+
if (!agentReturnTarget) {
|
|
650
|
+
finish(null, result);
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
pendingLoginResult = result;
|
|
654
|
+
if (timer)
|
|
655
|
+
clearTimeout(timer);
|
|
656
|
+
timer = setTimeout(() => finish(null, result), AGENT_RETURN_TIMEOUT_MS);
|
|
466
657
|
}
|
|
467
658
|
catch (exchangeError) {
|
|
468
659
|
const message = exchangeError instanceof Error ? exchangeError.message : String(exchangeError);
|
|
@@ -530,6 +721,7 @@ function registerBrowserLoginCommand(auth, action, name, description, behavior =
|
|
|
530
721
|
.option('--port <n>', 'Local OAuth callback port', '19800')
|
|
531
722
|
.option('--agent_type <value>', 'Agent type sent to E10 authorize endpoint')
|
|
532
723
|
.option('--agent-type <value>', 'Alias of --agent_type')
|
|
724
|
+
.option('--agent-return-url <url>', 'Desktop application URL linked by the login success page')
|
|
533
725
|
.action(action(async (ctx, options) => {
|
|
534
726
|
const result = await runBrowserLogin(ctx, options, behavior);
|
|
535
727
|
ctx.output.write(result, { text: formatLoginResult(result) });
|
|
@@ -617,6 +809,7 @@ export function registerE10AuthCommands(parent, action) {
|
|
|
617
809
|
registerBrowserLoginCommand(auth, action, 'login', 'Open browser OAuth2.0 login and save E10 auth');
|
|
618
810
|
registerBrowserLoginCommand(auth, action, 'oidc', 'Alias of auth login for OAuth2.0 browser login');
|
|
619
811
|
registerBrowserLoginCommand(auth, action, 'xiaoe', 'Try XiaoE unified login and explain before browser OAuth fallback', {
|
|
812
|
+
tryXiaoEUnifiedLogin: true,
|
|
620
813
|
allowXiaoETokenScript: true,
|
|
621
814
|
explainXiaoEFallback: true,
|
|
622
815
|
browserFallback: 'desktop-only',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createCipheriv, createDecipheriv, randomBytes } from 'node:crypto';
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
3
4
|
import { resolve } from 'node:path';
|
|
4
|
-
import { Entry as KeyringEntry } from '@napi-rs/keyring';
|
|
5
5
|
import { writeWithRetry } from '../../../core/write-with-retry.js';
|
|
6
6
|
import { getE10AuthRoot } from './paths.js';
|
|
7
7
|
const ALGORITHM = 'aes-256-gcm';
|
|
@@ -9,11 +9,40 @@ const IV_LENGTH = 12;
|
|
|
9
9
|
const TAG_LENGTH = 16;
|
|
10
10
|
const KEYCHAIN_SERVICE = 'weaver-work-cli';
|
|
11
11
|
const KEYCHAIN_ACCOUNT = 'auth-key';
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
12
13
|
let encKey = null;
|
|
14
|
+
let keyringEntryConstructor;
|
|
13
15
|
function getKeyFilePath() {
|
|
14
16
|
return resolve(getE10AuthRoot(), '.key');
|
|
15
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Load the native keyring binding only when auth encryption actually needs it.
|
|
20
|
+
*
|
|
21
|
+
* A top-level ESM import would dlopen the platform binary while the CLI command
|
|
22
|
+
* tree is being initialized. If a native dependency is unavailable (for
|
|
23
|
+
* example VCRUNTIME140.dll on Windows), even unrelated commands such as
|
|
24
|
+
* `--version` would terminate before the file-key fallback could run.
|
|
25
|
+
*/
|
|
26
|
+
function loadKeyringEntryConstructor() {
|
|
27
|
+
if (keyringEntryConstructor !== undefined)
|
|
28
|
+
return keyringEntryConstructor;
|
|
29
|
+
try {
|
|
30
|
+
const module = require('@napi-rs/keyring');
|
|
31
|
+
keyringEntryConstructor = typeof module.Entry === 'function'
|
|
32
|
+
? module.Entry
|
|
33
|
+
: null;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Missing packages, native dlopen failures and unavailable platform
|
|
37
|
+
// backends all use the existing encrypted file-key fallback.
|
|
38
|
+
keyringEntryConstructor = null;
|
|
39
|
+
}
|
|
40
|
+
return keyringEntryConstructor;
|
|
41
|
+
}
|
|
16
42
|
function readKeychainKey(service) {
|
|
43
|
+
const KeyringEntry = loadKeyringEntryConstructor();
|
|
44
|
+
if (!KeyringEntry)
|
|
45
|
+
return null;
|
|
17
46
|
try {
|
|
18
47
|
const entry = new KeyringEntry(service, KEYCHAIN_ACCOUNT);
|
|
19
48
|
const stored = entry.getPassword();
|
|
@@ -28,6 +57,19 @@ function readKeychainKey(service) {
|
|
|
28
57
|
}
|
|
29
58
|
return null;
|
|
30
59
|
}
|
|
60
|
+
function writeKeychainKey(service, key) {
|
|
61
|
+
const KeyringEntry = loadKeyringEntryConstructor();
|
|
62
|
+
if (!KeyringEntry)
|
|
63
|
+
return false;
|
|
64
|
+
try {
|
|
65
|
+
const entry = new KeyringEntry(service, KEYCHAIN_ACCOUNT);
|
|
66
|
+
entry.setPassword(key.toString('base64'));
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
31
73
|
function readKeyFile(filePath) {
|
|
32
74
|
if (!existsSync(filePath))
|
|
33
75
|
return null;
|
|
@@ -47,23 +89,21 @@ function getEncKey() {
|
|
|
47
89
|
encKey = storedKey;
|
|
48
90
|
return encKey;
|
|
49
91
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
entry.setPassword(fresh.toString('base64'));
|
|
54
|
-
encKey = fresh;
|
|
55
|
-
return encKey;
|
|
56
|
-
}
|
|
57
|
-
catch {
|
|
58
|
-
// Keychain may be unavailable in headless environments; fall back to a 0600 file.
|
|
59
|
-
}
|
|
92
|
+
// Reuse a previously created fallback key before generating a new keychain
|
|
93
|
+
// value. This keeps existing auth files decryptable if keyring availability
|
|
94
|
+
// changes between CLI runs.
|
|
60
95
|
const keyFile = getKeyFilePath();
|
|
61
96
|
const fileKey = readKeyFile(keyFile);
|
|
62
97
|
if (fileKey) {
|
|
63
98
|
encKey = fileKey;
|
|
64
99
|
return encKey;
|
|
65
100
|
}
|
|
66
|
-
|
|
101
|
+
const fresh = randomBytes(32);
|
|
102
|
+
if (writeKeychainKey(KEYCHAIN_SERVICE, fresh)) {
|
|
103
|
+
encKey = fresh;
|
|
104
|
+
return encKey;
|
|
105
|
+
}
|
|
106
|
+
encKey = fresh;
|
|
67
107
|
mkdirSync(getE10AuthRoot(), { recursive: true });
|
|
68
108
|
writeWithRetry(keyFile, encKey.toString('base64'), { mode: 0o600 });
|
|
69
109
|
return encKey;
|