@pippit-dev/cli 1.0.37 → 1.0.40
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 +86 -3
- package/checksums.txt +6 -6
- package/cmd/auth/auth.go +4 -3
- package/cmd/marketing.go +5 -4
- package/cmd/marketing_test.go +58 -0
- package/cmd/root.go +40 -14
- package/cmd/root_test.go +63 -0
- package/cmd/source_test.go +2 -3
- package/cmd/submit_run_test.go +20 -81
- package/cmd/update/update.go +36 -10
- package/cmd/update/update_test.go +73 -3
- package/dist/checksums.txt +6 -6
- package/dist/xyq-canvas-command-runtime.cjs +14 -14
- package/dist/xyq-canvas-command-runtime.cjs.LEGAL.txt +0 -206
- package/dist/xyq-canvas-command-runtime.cjs.sha256 +2 -2
- package/internal/adapter/adapter.go +73 -0
- package/internal/adapter/ppe.go +36 -0
- package/internal/adaptercli/commands.go +27 -0
- package/internal/adaptercli/commands_test.go +41 -0
- package/internal/auth/manager.go +25 -13
- package/internal/canvas/apply.go +3 -0
- package/internal/canvas/media_identity.go +300 -0
- package/internal/canvas/media_identity_test.go +160 -0
- package/internal/canvas/upload.go +30 -1
- package/internal/commandnames/names.go +9 -0
- package/internal/common/adapter_test.go +74 -0
- package/internal/common/client.go +37 -12
- package/internal/config/config.go +41 -0
- package/internal/config/config_test.go +41 -1
- package/internal/generate_video/generate_video.go +1 -0
- package/internal/generate_video/generate_video_test.go +25 -3
- package/internal/models/models.go +6 -2
- package/internal/models/models_test.go +7 -0
- package/package.json +2 -2
- package/scripts/canvas-command.js +4 -2
- package/scripts/install-wizard.js +3 -3
- package/scripts/install.js +1 -1
- package/scripts/telemetry.js +16 -0
- package/skills/short-drama/SKILL.md +6 -3
- package/skills/short-drama/commands/download-result.md +9 -3
- package/skills/short-drama/commands/get-thread.md +2 -0
- package/skills/short-drama/commands/list-thread-file.md +12 -6
- package/skills/short-drama/commands/submit-run.md +3 -1
- package/skills/short-drama/examples/create-and-deliver.md +2 -2
- package/skills/short-drama/examples/reference-and-continue.md +20 -1
- package/skills/short-drama/workflows/creation.md +28 -14
- package/skills/short-drama/workflows/poll-and-deliver.md +27 -9
- package/skills/xyq-nest-skill/commands/canvas-assets.md +9 -1
package/cmd/update/update.go
CHANGED
|
@@ -14,7 +14,9 @@ import (
|
|
|
14
14
|
"sync"
|
|
15
15
|
"time"
|
|
16
16
|
|
|
17
|
+
"github.com/Pippit-dev/pippit-cli/internal/adapter"
|
|
17
18
|
"github.com/Pippit-dev/pippit-cli/internal/auth"
|
|
19
|
+
"github.com/Pippit-dev/pippit-cli/internal/commandnames"
|
|
18
20
|
"github.com/Pippit-dev/pippit-cli/internal/version"
|
|
19
21
|
"github.com/spf13/cobra"
|
|
20
22
|
)
|
|
@@ -38,29 +40,53 @@ var telemetrySkillNames = []string{
|
|
|
38
40
|
"xyq-short-drama-skill",
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
// Each update command instance owns its HTTP client so instances using different adapters do not affect each other.
|
|
44
|
+
type updater struct{ telemetryHTTPClient *http.Client }
|
|
45
|
+
|
|
46
|
+
func newUpdater(policy adapter.HTTPAdapter) *updater {
|
|
47
|
+
return &updater{telemetryHTTPClient: &http.Client{
|
|
48
|
+
Timeout: telemetryWaitTimeout,
|
|
49
|
+
Transport: adapter.HTTPOrDefault(policy).WrapTransport(nil),
|
|
50
|
+
}}
|
|
51
|
+
}
|
|
42
52
|
|
|
43
53
|
// NewCommand builds the update command.
|
|
44
54
|
func NewCommand(stdout, stderr io.Writer) *cobra.Command {
|
|
55
|
+
return NewCommandWithAdapter(stdout, stderr, adapter.Default{})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
func NewCommandWithAdapter(stdout, stderr io.Writer, policy adapter.HTTPAdapter) *cobra.Command {
|
|
59
|
+
updater := newUpdater(policy)
|
|
45
60
|
var source string
|
|
61
|
+
var channel string
|
|
46
62
|
cmd := &cobra.Command{
|
|
47
|
-
Use:
|
|
63
|
+
Use: commandnames.Update,
|
|
48
64
|
Short: "Update pippit-tool-cli and bundled skills",
|
|
49
65
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
50
66
|
if !cmd.Flags().Changed("source") {
|
|
51
67
|
source = os.Getenv("PIPPIT_CLI_SOURCE")
|
|
52
68
|
}
|
|
53
|
-
return runUpdate(stdout, stderr, source)
|
|
69
|
+
return updater.runUpdate(stdout, stderr, source, channel)
|
|
54
70
|
},
|
|
55
71
|
}
|
|
56
72
|
cmd.Flags().StringVar(&source, "source", "", "optional real host identifier reported as host_platform; defaults to PIPPIT_CLI_SOURCE when unset")
|
|
73
|
+
cmd.Flags().StringVar(&channel, "channel", "", "channel for this update only: stable (npm latest) or canary; overrides PIPPIT_CLI_INSTALL_PACKAGE")
|
|
57
74
|
return cmd
|
|
58
75
|
}
|
|
59
76
|
|
|
60
|
-
func runUpdate(stdout, stderr io.Writer,
|
|
77
|
+
func (u *updater) runUpdate(stdout, stderr io.Writer, hostPlatform, channel string) error {
|
|
61
78
|
pkg := os.Getenv("PIPPIT_CLI_INSTALL_PACKAGE")
|
|
62
|
-
|
|
79
|
+
switch channel {
|
|
80
|
+
case "":
|
|
81
|
+
if pkg == "" {
|
|
82
|
+
pkg = defaultPackage + "@latest"
|
|
83
|
+
}
|
|
84
|
+
case "stable":
|
|
63
85
|
pkg = defaultPackage + "@latest"
|
|
86
|
+
case "canary":
|
|
87
|
+
pkg = defaultPackage + "@canary"
|
|
88
|
+
default:
|
|
89
|
+
return fmt.Errorf("不支持的更新渠道 %q,可选值为 stable 或 canary", channel)
|
|
64
90
|
}
|
|
65
91
|
|
|
66
92
|
fmt.Fprintf(stderr, "Updating pippit-tool-cli via npm: %s\n", pkg)
|
|
@@ -83,7 +109,7 @@ func runUpdate(stdout, stderr io.Writer, source string) error {
|
|
|
83
109
|
return fmt.Errorf("更新 pippit-tool-cli skills 失败: %w", err)
|
|
84
110
|
}
|
|
85
111
|
|
|
86
|
-
reportBundledSkillTelemetry("update", "cli_update",
|
|
112
|
+
u.reportBundledSkillTelemetry("update", "cli_update", hostPlatform, stderr)
|
|
87
113
|
fmt.Fprintln(stdout, "pippit-tool-cli and skills updated")
|
|
88
114
|
return nil
|
|
89
115
|
}
|
|
@@ -143,7 +169,7 @@ type telemetryPayload struct {
|
|
|
143
169
|
Arch string `json:"arch"`
|
|
144
170
|
}
|
|
145
171
|
|
|
146
|
-
func reportBundledSkillTelemetry(event, source, hostPlatform string, stderr io.Writer) {
|
|
172
|
+
func (u *updater) reportBundledSkillTelemetry(event, source, hostPlatform string, stderr io.Writer) {
|
|
147
173
|
if os.Getenv("PIPPIT_CLI_DISABLE_TELEMETRY") == "1" {
|
|
148
174
|
return
|
|
149
175
|
}
|
|
@@ -161,7 +187,7 @@ func reportBundledSkillTelemetry(event, source, hostPlatform string, stderr io.W
|
|
|
161
187
|
wg.Add(1)
|
|
162
188
|
go func(payload telemetryPayload) {
|
|
163
189
|
defer wg.Done()
|
|
164
|
-
if err := reportSkillTelemetry(payload); err != nil && os.Getenv("PIPPIT_CLI_DEBUG_TELEMETRY") == "1" {
|
|
190
|
+
if err := u.reportSkillTelemetry(payload); err != nil && os.Getenv("PIPPIT_CLI_DEBUG_TELEMETRY") == "1" {
|
|
165
191
|
fmt.Fprintf(stderr, "[pippit-tool-cli] 埋点上报失败: %v\n", err)
|
|
166
192
|
}
|
|
167
193
|
}(payload)
|
|
@@ -177,7 +203,7 @@ func reportBundledSkillTelemetry(event, source, hostPlatform string, stderr io.W
|
|
|
177
203
|
}
|
|
178
204
|
}
|
|
179
205
|
|
|
180
|
-
func reportSkillTelemetry(payload telemetryPayload) error {
|
|
206
|
+
func (u *updater) reportSkillTelemetry(payload telemetryPayload) error {
|
|
181
207
|
body, err := json.Marshal(payload)
|
|
182
208
|
if err != nil {
|
|
183
209
|
return err
|
|
@@ -190,7 +216,7 @@ func reportSkillTelemetry(payload telemetryPayload) error {
|
|
|
190
216
|
req.Header.Set("Content-Type", "application/json")
|
|
191
217
|
req.Header.Set("Authorization", telemetryAuthHeader)
|
|
192
218
|
|
|
193
|
-
resp, err := telemetryHTTPClient.Do(req)
|
|
219
|
+
resp, err := u.telemetryHTTPClient.Do(req)
|
|
194
220
|
if err != nil {
|
|
195
221
|
return err
|
|
196
222
|
}
|
|
@@ -11,8 +11,78 @@ import (
|
|
|
11
11
|
"strings"
|
|
12
12
|
"testing"
|
|
13
13
|
"time"
|
|
14
|
+
|
|
15
|
+
"github.com/Pippit-dev/pippit-cli/internal/adapter"
|
|
14
16
|
)
|
|
15
17
|
|
|
18
|
+
func TestUpdateCommandSelectsChannel(t *testing.T) {
|
|
19
|
+
if runtime.GOOS == "windows" {
|
|
20
|
+
t.Skip("test uses POSIX shell scripts to stub npm and npx")
|
|
21
|
+
}
|
|
22
|
+
cases := []struct {
|
|
23
|
+
name string
|
|
24
|
+
args []string
|
|
25
|
+
override string
|
|
26
|
+
want string
|
|
27
|
+
wantErr bool
|
|
28
|
+
}{
|
|
29
|
+
{name: "default stable", want: defaultPackage + "@latest"},
|
|
30
|
+
{name: "explicit stable", args: []string{"--channel", "stable"}, want: defaultPackage + "@latest"},
|
|
31
|
+
{name: "explicit canary", args: []string{"--channel", "canary"}, want: defaultPackage + "@canary"},
|
|
32
|
+
{name: "package override preserved", override: defaultPackage + "@1.0.38", want: defaultPackage + "@1.0.38"},
|
|
33
|
+
{name: "stable overrides environment", args: []string{"--channel", "stable"}, override: defaultPackage + "@canary", want: defaultPackage + "@latest"},
|
|
34
|
+
{name: "canary overrides environment", args: []string{"--channel", "canary"}, override: defaultPackage + "@1.0.38", want: defaultPackage + "@canary"},
|
|
35
|
+
{name: "invalid channel", args: []string{"--channel", "beta"}, wantErr: true},
|
|
36
|
+
{name: "invalid channel with override", args: []string{"--channel", "beta"}, override: defaultPackage + "@1.0.38", wantErr: true},
|
|
37
|
+
}
|
|
38
|
+
for _, tc := range cases {
|
|
39
|
+
t.Run(tc.name, func(t *testing.T) {
|
|
40
|
+
binDir := t.TempDir()
|
|
41
|
+
npmRoot := t.TempDir()
|
|
42
|
+
capturePath := filepath.Join(t.TempDir(), "npm-args.txt")
|
|
43
|
+
if err := os.MkdirAll(filepath.Join(npmRoot, "@pippit-dev", "cli", "skills"), 0o755); err != nil {
|
|
44
|
+
t.Fatal(err)
|
|
45
|
+
}
|
|
46
|
+
npmScript := "#!/bin/sh\ncase \"$1\" in\ninstall) printf '%s\\n' \"$@\" > \"$CAPTURE_ARGS\";;\nroot) printf '%s\\n' \"$TEST_NPM_ROOT\";;\n*) exit 1;;\nesac\n"
|
|
47
|
+
for name, script := range map[string]string{"npm": npmScript, "npx": "#!/bin/sh\nexit 0\n"} {
|
|
48
|
+
if err := os.WriteFile(filepath.Join(binDir, name), []byte(script), 0o755); err != nil {
|
|
49
|
+
t.Fatal(err)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
|
|
53
|
+
t.Setenv("HOME", t.TempDir())
|
|
54
|
+
t.Setenv("CAPTURE_ARGS", capturePath)
|
|
55
|
+
t.Setenv("TEST_NPM_ROOT", npmRoot)
|
|
56
|
+
t.Setenv("PIPPIT_CLI_DISABLE_TELEMETRY", "1")
|
|
57
|
+
t.Setenv("PIPPIT_CLI_INSTALL_PACKAGE", tc.override)
|
|
58
|
+
var stdout, stderr bytes.Buffer
|
|
59
|
+
cmd := NewCommand(&stdout, &stderr)
|
|
60
|
+
cmd.SetArgs(append([]string{}, tc.args...))
|
|
61
|
+
err := cmd.Execute()
|
|
62
|
+
if tc.wantErr {
|
|
63
|
+
if err == nil || !strings.Contains(err.Error(), "不支持的更新渠道") {
|
|
64
|
+
t.Fatalf("error = %v, want invalid channel error", err)
|
|
65
|
+
}
|
|
66
|
+
if _, err := os.Stat(capturePath); !os.IsNotExist(err) {
|
|
67
|
+
t.Fatalf("invalid channel invoked npm or stat failed: %v", err)
|
|
68
|
+
}
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
if err != nil {
|
|
72
|
+
t.Fatalf("update failed: %v, stderr: %s", err, stderr.String())
|
|
73
|
+
}
|
|
74
|
+
got, err := os.ReadFile(capturePath)
|
|
75
|
+
if err != nil {
|
|
76
|
+
t.Fatal(err)
|
|
77
|
+
}
|
|
78
|
+
want := strings.Join([]string{"install", "-g", "--prefer-online", "--foreground-scripts", tc.want, ""}, "\n")
|
|
79
|
+
if string(got) != want {
|
|
80
|
+
t.Fatalf("npm args = %q, want %q", got, want)
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
16
86
|
func TestInstallSkillsInstallsAllBundledSkills(t *testing.T) {
|
|
17
87
|
if runtime.GOOS == "windows" {
|
|
18
88
|
t.Skip("test uses a POSIX shell script to stub npx")
|
|
@@ -92,7 +162,7 @@ func TestReportSkillTelemetry(t *testing.T) {
|
|
|
92
162
|
defer server.Close()
|
|
93
163
|
|
|
94
164
|
t.Setenv("PIPPIT_CLI_TELEMETRY_BASE_URL", server.URL+"/")
|
|
95
|
-
err := reportSkillTelemetry(telemetryPayload{
|
|
165
|
+
err := newUpdater(adapter.Default{}).reportSkillTelemetry(telemetryPayload{
|
|
96
166
|
Event: "update",
|
|
97
167
|
SkillName: "xyq-skill",
|
|
98
168
|
Source: "cli_update",
|
|
@@ -121,7 +191,7 @@ func TestReportBundledSkillTelemetryWaitsBriefly(t *testing.T) {
|
|
|
121
191
|
|
|
122
192
|
t.Setenv("PIPPIT_CLI_TELEMETRY_BASE_URL", server.URL)
|
|
123
193
|
start := time.Now()
|
|
124
|
-
reportBundledSkillTelemetry("update", "cli_update", " workbuddy ", &bytes.Buffer{})
|
|
194
|
+
newUpdater(adapter.Default{}).reportBundledSkillTelemetry("update", "cli_update", " workbuddy ", &bytes.Buffer{})
|
|
125
195
|
if elapsed := time.Since(start); elapsed > 1500*time.Millisecond {
|
|
126
196
|
t.Fatalf("reportBundledSkillTelemetry() blocked for %v, want <= 1.5s", elapsed)
|
|
127
197
|
}
|
|
@@ -143,7 +213,7 @@ func TestReportBundledSkillTelemetryReportsBothSkills(t *testing.T) {
|
|
|
143
213
|
defer server.Close()
|
|
144
214
|
|
|
145
215
|
t.Setenv("PIPPIT_CLI_TELEMETRY_BASE_URL", server.URL)
|
|
146
|
-
reportBundledSkillTelemetry("update", "cli_update", " workbuddy ", &bytes.Buffer{})
|
|
216
|
+
newUpdater(adapter.Default{}).reportBundledSkillTelemetry("update", "cli_update", " workbuddy ", &bytes.Buffer{})
|
|
147
217
|
|
|
148
218
|
got := map[string]bool{}
|
|
149
219
|
for i := 0; i < len(telemetrySkillNames); i++ {
|
package/dist/checksums.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
14eec459ef3d526057582d47ec5611a48146b825181f06652f31c76e203a7f9c pippit-tool-cli-1.0.40-darwin-amd64.tar.gz
|
|
2
|
+
81d6967ef44953e91d9a2504bba20979570de7c0554aae4d7b55660da9fb32e8 pippit-tool-cli-1.0.40-darwin-arm64.tar.gz
|
|
3
|
+
8811832e3c840cb0418654953f354b254f3889346966c161ab65279f0cf03662 pippit-tool-cli-1.0.40-linux-amd64.tar.gz
|
|
4
|
+
28ce9f374f34fed4fa3e7b44a2b1b1fcc59c8cd7d83ad7621e8c694dd35194ad pippit-tool-cli-1.0.40-linux-arm64.tar.gz
|
|
5
|
+
ffd11a5de082b50b54d8b9f701890186c28785bca4cfd6e8e05254ce6eed965c pippit-tool-cli-1.0.40-windows-amd64.zip
|
|
6
|
+
88ed4320bbef1146355890753226ec6a99b0f0653556e1a4665ad7f23dd17c30 pippit-tool-cli-1.0.40-windows-arm64.zip
|